);
+```
+
+## How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes
+For the new decoders for **NEC, Panasonic, Sony, Samsung and JVC**, the result `IrReceiver.decodedIRData.decodedRawData` is now **LSB-first**, as the definition of these protocols suggests!
+
+To convert one into the other, you must reverse the nibble (4 bit / Hex numbers) positions and then reverse all bit positions of each nibble or write it as one binary string and reverse/mirror it.
+This can be done by using the new functions `bitreverseOneByte()` or `bitreverse32Bit()`.
+
+### Nibble reverse
+`0xCB 34 01 02` MSB value
+`0x20 10 43 BC` after nibble reverse
+`0x40 80 2C D3` LSB value after bit reverse of each nibble
+
+### Nibble reverse map
+```
+ 0->0 1->8 2->4 3->C
+ 4->2 5->A 6->6 7->E
+ 8->1 9->9 A->5 B->D
+ C->3 D->B E->7 F->F
+```
+
+### Binary string reverse
+If you **read the first binary sequence backwards** (right to left), you get the second sequence.
+`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
+`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.
+
+### Online tool which reverses every byte, but not the order of the bytes
+Use this [tool provided by analysir](https://www.analysir.com/hex2nec.php).
+
+### Send MSB directly
+Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
+
+
+
+## Errors when using the 4.x versions for old tutorials
+If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`,
+just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
+Most likely your code will run and you will not miss the new features.
+
+
+
+## Staying on 2.x
+Consider using the [original 2.4 release from 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0)
+or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
+It may be sufficient and deals flawlessly with 32 bit IR codes.
+If this doesn't work for you, you can be sure that 4.x is trying to be compatible with earlier versions, so your old examples should work just fine.
+
+### Drawbacks of using 2.x
+- Only the following decoders are available:
+ ` NEC ` ` Denon ` ` Panasonic ` ` JVC ` ` LG `
+ ` RC5 ` ` RC6 ` ` Samsung ` ` Sony `
+- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`.
+- No decoding to a more meaningful (constant) 8/16 bit address and 8 bit command.
diff --git a/README.md b/README.md
index 5d186af5f..9b3d9c64a 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
# Arduino IRremote
-A library enabling the sending & receiving of infra-red signals.
+A library enabling the sending & receiving of infrared signals.
[](https://opensource.org/licenses/MIT)
-[](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest)
+[](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest)
[](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)
@@ -24,68 +24,92 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
[](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributing.md)
+#### If you find this program useful, please give it a star.
+
+🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/Arduino-IRremote/Arduino-IRremote)
+
-# Overview
-- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-ir-protocols)
-- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote#features)
- * [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-4x)
- * [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-3x)
-- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version)
- * [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes)
-- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote#errors-with-using-the-3x-versions-for-old-tutorials)
- * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote#staying-on-2x)
-- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-instead-of-cpp)
-- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files)
-- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes)
- * [Data format](https://github.com/Arduino-IRremote/Arduino-IRremote#data-format)
- * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#ambiguous-protocols)
-- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes)
- * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote#send-pin)
- + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases)
-- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote#tiny-nec-receiver-and-sender)
-- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#the-fast-protocol)
-- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote#faq-and-hints)
- * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc)
- * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote#does-not-workcompile-with-another-library)
- * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#multiple-ir-receiver)
- * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote#increase-strength-of-sent-output-signal)
- * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-cpu-clock-frequency)
- * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#bang--olufsen-protocol)
-- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#handling-unknown-protocols)
- * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote#disclaimer)
- * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolpulse_distance)
- * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown)
- * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-deal-with-protocols-not-supported-by-irremote)
-- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library)
-- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote#wokwi-online-examples)
-- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote#issues-and-discussions)
-- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library)
- + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#changing-include-h-files-with-arduino-ide)
- + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#modifying-compile-options--macros-with-sloeber-ide)
-- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-boards)
-- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage)
- * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite)
- * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#hardware-pwm-signal-generation-for-sending)
- * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#why-do-we-use-30-duty-cycle-for-sending)
-- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote#how-we-decode-signals)
-- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote#nec-encoding-diagrams)
-- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries)
-- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote#useful-links)
+# Table of contents
+- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols)
+- [Common issues when using IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-issues-when-using-irremote)
+- [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Migrating.md)
+ * [New features and changes in version 4.6](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-version-46)
+- [Why *.hpp instead of *.cpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp-files)
+- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files)
+- [Tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tutorials)
+- [3 ways to specify an IR code](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#3-ways-to-specify-an-ir-code)
+- [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts)
+- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes)
+ * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure)
+ * [Callback functionality](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#callback-functionality)
+ * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols)
+ * [RAM usage of different protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ram-usage-of-different-protocols)
+ * [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols)
+ * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer)
+ * [Other libraries, which may cover these protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#other-libraries-which-may-cover-these-protocols)
+ * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance)
+ * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown)
+ * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote)
+ * [Multiple IR receivers](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receivers)
+- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes)
+ * [Sending UNKNOWN protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-unknown-protocol)
+ * [Sending protocol from description](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-protocol-from-description)
+ * [Sending IRDB IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-irdb-ir-codes)
+ + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases)
+ * [Flipper Zero Codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#flipper-zero-codes)
+ * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin)
+ * [Polarity of send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#polarity-of-send-pin)
+ * [Simulate an IR receiver module for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module-for-sending)
+ * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#increase-strength-of-sent-output-signal)
+ * [Multiple IR sender instances](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-sender-instances)
+- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender)
+- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol)
+- [Feedback LED](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#feedback-led)
+- [IRCommandDispatcher class](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ircommanddispatcher-class)
+- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints)
+ * [Receiving stops after analogWrite() or tone() or after running a motor](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor)
+ * [Receiving sets overflow flag](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-sets-overflow-flag)
+ * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc)
+ * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library)
+ * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency)
+ * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol)
+- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library)
+- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#wokwi-online-examples)
+- [IR control of a robot car](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ir-control-of-a-robot-car)
+- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#issues-and-discussions)
+- [Compile options / macros for IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-irremote)
+- [Macros for TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#macros-for-tinyir)
+- [Macros for IRCommandDispatcher](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#macros-for-ircommanddispatcher)
+ + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#changing-include-h-files-with-arduino-ide)
+ + [Modifying compile options / macros with PlatformIO](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-platformio)
+ + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide)
+- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-boards)
+- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage)
+ * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite)
+ * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#hardware-pwm-signal-generation-for-sending)
+ * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-do-we-use-30-duty-cycle-for-sending)
+- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-we-decode-signals)
+- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#nec-encoding-diagrams)
+- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries)
+- [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md)
+- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#useful-links)
- [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md)
-- [License](https://github.com/Arduino-IRremote/Arduino-IRremote#license)
-- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote#copyright)
+- [License](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#license)
+- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#copyright)
# Supported IR Protocols
-` NEC / Onkyo / Apple ` ` Denon / Sharp ` ` Panasonic / Kaseikyo `
+` NEC / Onkyo / Apple `, ` Denon / Sharp `, ` Panasonic / Kaseikyo `,
-` JVC ` ` LG ` ` RC5 ` ` RC6 ` ` Samsung ` ` Sony `
+` JVC `, ` LG `, ` RC5 `, ` RC6 `, ` Samsung `, ` Sony `, ` Marantz `
-` Universal Pulse Distance ` ` Universal Pulse Width ` ` Hash ` ` Pronto `
+` Universal Pulse Distance `, ` Universal Pulse Width `, ` Universal Pulse Distance Width`
-` BoseWave ` ` Bang & Olufsen ` ` Lego ` ` FAST ` ` Whynter ` ` MagiQuest `
+` Hash `, ` Pronto `
+
+` BoseWave `, ` Bang & Olufsen `, ` Lego `, ` FAST `, ` Whynter `, ` Marantz `, ` MagiQuest `, ` Velux `, ` OpenLASIR `
Protocols can be switched off and on by defining macros before the line `#include ` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33):
@@ -96,162 +120,35 @@ Protocols can be switched off and on by defining macros before the line `#includ
```
-# Features
-- Lots of tutorials and examples.
-- Actively maintained.
-- Allows receiving and sending of **raw timing data**.
-
-## New features with version 4.x
-- New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols.
-- Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`.
-- RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before.
-- Callback after receiving a command - It calls your code as soon as a message was received.
-- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols.
-- New FAST protocol.
-
-#### Converting your 3.x program to the 4.x version
-- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder).
-- The parameter `bool hasStopBit` is not longer required and removed e.g. for function `sendPulseDistanceWidth()`.
-
-## New features with version 3.x
-- **Any pin** can be used for sending -if `SEND_PWM_BY_TIMER` is not defined- and receiving.
-- Feedback LED can be activated for sending / receiving.
-- An 8/16 bit ****command** value as well as an 16 bit **address** and a protocol number is provided for decoding (instead of the old 32 bit value).
-- Protocol values comply to **protocol standards**.
- NEC, Panasonic, Sony, Samsung and JVC decode & send LSB first.
-- Supports **Universal Distance protocol**, which covers a lot of previous unknown protocols.
-- Compatible with **tone()** library. See the [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169) example.
-- Simultaneous sending and receiving. See the [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino#L167-L170) example.
-- Supports **more platforms**.
-- Allows for the generation of non PWM signal to just **simulate an active low receiver signal** for direct connect to existent receiving devices without using IR.
-- Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
- Reduces memory footprint and decreases decoding time.
-- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver), which **does not require any timer resource**.
-
-[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries).
+# Common issues when using IRremote
+Or *"I build a gadget with 2 motors controlled by IR and the [IR stops after the first motor command](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor)"*.
+This is due to the fact, that the motor control by AnalogWrite() uses the same timer as IR receiving.
+See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) for the list of timers and pins.
-# Converting your 2.x program to the 4.x version
-Starting with the 3.1 version, **the generation of PWM for sending is done by software**, thus saving the hardware timer and **enabling arbitrary output pins for sending**.
-If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, if you get false error messages regarding begin() during compilation.
-
-- **IRreceiver** and **IRsender** object have been added and can be used without defining them, like the well known Arduino **Serial** object.
-- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program, and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`.
-- Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar.
-- Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106)
- or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin(ENABLE_LED_FEEDBACK);` or `IrSender.begin(DISABLE_LED_FEEDBACK);` in setup().
-If IR_SEND_PIN is not defined you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);`
-- Old `decode(decode_results *aResults)` function is replaced by simple `decode()`. So if you have a statement `if(irrecv.decode(&results))` replace it with `if (IrReceiver.decode())`.
-- The decoded result is now in in `IrReceiver.decodedIRData` and not in `results` any more, therefore replace any occurrences of `results.value` and `results.decode_type` (and similar) to
- `IrReceiver.decodedIRData.decodedRawData` and `IrReceiver.decodedIRData.protocol`.
-- Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L90-L101).
-- Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`.
-
-- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data for **NEC** and **JVC** were renamed to `sendNECMSB`, and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized.
-For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes).
-
-### Example
-#### Old 2.x program:
-
-```c++
-#include
-
-IRrecv irrecv(RECV_PIN);
-decode_results results;
-
-void setup()
-{
-...
- irrecv.enableIRIn(); // Start the receiver
-}
-
-void loop() {
- if (irrecv.decode(&results)) {
- Serial.println(results.value, HEX);
- ...
- irrecv.resume(); // Receive the next value
- }
- ...
-}
-```
-
-#### New 4.x program:
+# [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Migrating.md)
-```c++
-#include
-
-void setup()
-{
-...
- IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
-}
-
-void loop() {
- if (IrReceiver.decode()) {
- Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
- // USE NEW 3.x FUNCTIONS
- IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
- IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
- ...
- IrReceiver.resume(); // Enable receiving of the next value
- }
- ...
-}
-```
+## New features and changes in version 4.6
+** Version 4.5.0 does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt.**
+- Support for **multiple receiver instances**.
+`irparams_struct irparams` is now member of `IRrecv`. Thus `rawDataPtr` (pointer to irparams) was removed from `IrReceiver.decodedIRData`.
+Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.rawbuf`, the same holds for `IrReceiver.irparams.rawlen`.
+- LED feedback is always enabled for sending. It can only be disabled by using `#define NO_LED_SEND_FEEDBACK_CODE` or `#define NO_LED_FEEDBACK_CODE`.
+- The second parameter of the function `IrSender.begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback)` has changed to `uint_fast8_t aFeedbackLEDPin`. Therefore this function call no longer works as expected because it uses the old boolean value of e.g. `ENABLE_LED_FEEDBACK` which evaluates to true or 1 as pin number of the LED feedback pin number.
+- New experimental Velux send function.
+- Send function for Marantz version of the RC5x protocol. This protocol has an additional 6 bit command extension and adds a short pause after the address is sent to identify this variant of the protocol.
-## How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes
-For the new decoders for **NEC, Panasonic, Sony, Samsung and JVC**, the result `IrReceiver.decodedIRData.decodedRawData` is now **LSB-first**, as the definition of these protocols suggests!
-To convert one into the other, you must reverse the byte/nibble positions and then reverse all bit positions of each byte/nibble or write it as one binary string and reverse/mirror it.
-Example:
-`0xCB 34 01 02`
-`0x20 10 43 BC` after nibble reverse
-`0x40 80 2C D3` after bit reverse of each nibble
-### Nibble reverse map:
-```
- 0->0 1->8 2->4 3->C
- 4->2 5->A 6->6 7->E
- 8->1 9->9 A->5 B->D
- C->3 D->B E->7 F->F
-```
-`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
-`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.
-If you **read the first binary sequence backwards** (right to left), you get the second sequence.
-
-
-
-# Errors with using the 4.x versions for old tutorials
-If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
-Most likely your code will run and you will not miss the new features...
-
-
-## Staying on 2.x
-Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0)
-or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
-It may be sufficient and deals flawlessly with 32 bit IR codes.
-If this doesn't fit your case, be assured that 3.x is at least trying to be backwards compatible, so your old examples should still work fine.
-
-### Drawbacks
-- Only the following decoders are available:
- ` NEC ` ` Denon ` ` Panasonic ` ` JVC ` ` LG `
- ` RC5 ` ` RC6 ` ` Samsung ` ` Sony `
-- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`.
-- The old functions `sendNEC()` and `sendJVC()` are renamed to `sendNECMSB()` and `sendJVCMSB()`.
- Use them to send your **old MSB-first 32 bit IR data codes**.
-- No decoding by a (constant) 8/16 bit address and an 8 bit command.
-
-
-
-# Why *.hpp instead of *.cpp?
+# Why *.hpp instead of *.cpp files?
**Every \*.cpp file is compiled separately** by a call of the compiler exclusively for this cpp file. These calls are managed by the IDE / make system.
In the Arduino IDE the calls are executed when you click on *Verify* or *Upload*.
-And now our problem with Arduino is:
-**How to set [compile options](#compile-options--macros-for-this-library) for all *.cpp files, especially for libraries used?**
-IDE's like [Sloeber](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-sloeber-ide) or [PlatformIO](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project.
+And now **our problem with Arduino** is:
+**How to set [compile options](#compile-options--macros-for-irremote) for all *.cpp files, especially for libraries used?**
+IDE's like [Sloeber](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) or
+[PlatformIO](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project.
They add these options at each compiler call e.g. `-DTRACE`.
But Arduino lacks this feature.
@@ -259,14 +156,14 @@ So the **workaround** is not to compile all sources separately, but to concatena
This is done by e.g. `#include "IRremote.hpp"`.
But why not `#include "IRremote.cpp"`?
-Try it and you will see tons of errors, because each function of the *.cpp file is now compiled twice,
-first by compiling the huge file and second by compiling the *.cpp file separately, like described above.
-So using the extension *cpp* is not longer possible, and one solution is to use *hpp* as extension, to show that it is an included *.cpp file.
-Every other extension e.g. *cinclude* would do, but *hpp* seems to be common sense.
+If you try it, you will see lots of errors, because each function of the *.cpp file is now compiled twice:
+first when the huge file is compiled, and second when the .cpp file is compiled separately, as described above.
+Therefore, using the **.cpp** extension is no longer possible. One solution is to use the **.hpp** extension to indicate that it is an included .cpp file.
+Any other extension would work, e.g. *cinclude*, but *hpp* seems to be common sense.
# Using the new *.hpp files
-In order to support [compile options](#compile-options--macros-for-this-library) more easily,
-you must use the statement `#include ` instead of `#include ` in your main program (aka *.ino file with setup() and loop()).
+In order to support [compile options](#compile-options--macros-for-irremote) more easily,
+you **must** use the statement `#include ` instead of `#include ` in your main program (aka *.ino file with setup() and loop()).
In **all other files** you must use the following, to **prevent `multiple definitions` linker errors**:
@@ -283,39 +180,99 @@ The following macros will definitely be overridden with default values otherwise
+# Tutorials
+- A very elaborated introduction to IR remotes and IRremote library from [DroneBot Workshop ](https://dronebotworkshop.com/ir-remotes/).
+
+
+# 3 ways to specify an IR code
+There are 3 different ways of specifying a particular IR code.
+- **Timing (Raw):** Records the exact duration of pulses. Uses the most memory but works for everything.
+- **Encoding Schemes:** General rules for each data bit (like how 1s and 0s are shaped).
+- **Protocols (Recommended):** Uses predefined names (like NEC or Sony) and small 8 or 16-bit addresses and commands. Most efficient and easiest to read.
+
+## 1. Timing
+The timing of each mark/pulse and space/distance_between_pulses is specified in a list or array.
+This enables specifying **all IR codes**, but requires a lot of memory and is **not readable at all**.
+One formal definition of such a timing array, including **specification of frequency and repeats** is the [**Pronto** format](http://www.harctoolbox.org/Glossary.html#ProntoSemantics).
+Memory can be saved by using a lower time resolution.
+For IRremote you can use a 50 µs resolution which halves the memory requirement by using byte values instead of int16 values.
+For receiving purposes you can use the **hash of the timing** provided by the `decodeHash()` decoder.
+
+## 2. Encoding schemes
+There are 3 main encoding schemes which encode a binary bitstream / hex value:
+1. `PULSE_DISTANCE`. The distance between pulses determines the bit value. This always requires a stop bit!
+Examples are NEC and KASEIKYO protocols. The pulse width is constant for most protocols.
+2. `PULSE_WIDTH`. The width of a pulse determines the bit value, pulse distance is constant. This requires no stop bit!
+The only known example is the SONY protocol.
+3. [Phase / Manchester encoding](https://en.wikipedia.org/wiki/Manchester_code).
+The time of the pulse/pause transition (phase) relative to the clock determines the bit value. Examples are RC5 and RC6 protocols.
+
+Phase encoding has a **constant bit length**, `PULSE_DISTANCE` with constant pulse width and `PULSE_WIDTH` have **no constant bit length**!
+
+A well known example for `PULSE_DISTANCE` with non constant pulse width encoding is the **RS232 serial encoding**.
+Here the non constant pulse width is used to enable a **constant bit length**.
+
+Most IR signals have a **special header** to help in setting the automatic gain of the receiver circuit.
+This header is not part of the encoding, but is often significant for a special protocol and therefore must be reproducible.
+
+Be aware that there are codes using a `PULSE_DISTANCE` encoding where more than a binary 0/1 is put into a pulse/pause combination.
+This requires more than 2 different pulse or pause length combinations.
+The [HobToHood protocol](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino) uses such an encoding.
+
+Using encoding schemes reduces the specification of an IR code to a bitstream / hex value, which is LSB by default and pulse / pause timings of header, 0, and 1.
+The hex value is **quite readable**.
+These schemes can not put any semantics like address, command or checksum on this bitstream.
+
+## 3. Protocols
+There are a few common protocols that are implemented directly in IRremote.
+They specify the frequency, the timings of header, 0, and 1 as well as other values like checksum, repeat distance, repeat coding, bit toggling etc.
+The semantics of the hex value is also specified, allowing the usage of only 2 parameters **address** and **command** to specify an IR code.
+This saves memory and is **highly readable**.
+Often the address is also constant, which further reduces memory requirements.
+
+
+# IRReceiver pinouts
+
+
+[Adafruit IR Sensor tutorial](https://learn.adafruit.com/ir-sensor)
+
+
# Receiving IR codes
-Check for **received data** with:
+In your program you check for a **completely received IR frame** with:
`if (IrReceiver.decode()) {}`
-This also decodes the received data.
-
-## Data format
+This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`.
+## decodedIRData structure
```c++
struct IRData {
decode_type_t protocol; // UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
uint16_t address; // Decoded address
uint16_t command; // Decoded command
uint16_t extra; // Used for Kaseikyo unknown vendor ID. Ticks used for decoding Distance protocol.
+ IRDecodedRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions.
+#if defined(DECODE_DISTANCE_WIDTH)
+ DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes
+ IRDecodedRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; // 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions.
+#endif
uint16_t numberOfBits; // Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; // IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions
- IRRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions.
- uint32_t decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; // 32 bit decoded raw data, to be used for send function.
- irparams_struct *rawDataPtr; // Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
+ IRRawlenType rawlen; // Counter of entries in rawbuf of last received frame.
+ uint16_t initialGapTicks; // Contains the initial gap of the last received frame.
};
```
#### Flags
-This is the [list of flags](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L88) contained in the flags field.
+This is the [list of flags](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L143) contained in the flags field.
Check it with e.g. `if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)`.
| Flag name | Description |
|:---|----|
-| IRDATA_FLAGS_IS_REPEAT | The gap between the preceding frame is as smaller than the maximum gap expected for a repeat. !!!We do not check for changed command or address, because it is almost not possible to press 2 different buttons on the remote within around 100 ms!!!
+| IRDATA_FLAGS_IS_REPEAT | The gap between the preceding frame is as smaller than the maximum gap expected for a repeat. !!!We do not check for changed command or address, because it is virtually impossible to press 2 different buttons on the remote within around 100 ms!!!
| IRDATA_FLAGS_IS_AUTO_REPEAT | The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided. Only specified for protocols DENON, and LEGO. |
| IRDATA_FLAGS_PARITY_FAILED | The current (autorepeat) frame violated parity check. |
| IRDATA_FLAGS_TOGGLE_BIT | Is set if RC5 or RC6 toggle bit is set. |
| IRDATA_FLAGS_EXTRA_INFO | There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID, or in decodedRawDataArray). |
-| IRDATA_FLAGS_WAS_OVERFLOW | irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag. |
+| IRDATA_FLAGS_WAS_OVERFLOW | Too many marks and spaces for the specified `RAW_BUFFER_LENGTH`. To avoid endless flagging of overflow, irparams.rawlen is set to 0 in this case. |
| IRDATA_FLAGS_IS_MSB_FIRST | This value is mainly determined by the (known) protocol. |
#### To access the **RAW data**, use:
@@ -334,15 +291,21 @@ IrReceiver.printIRResultShort(&Serial);
```c++
IrReceiver.printIRResultRawFormatted(&Serial, true);`
```
-The raw data depends on the internal state of the Arduino timer in relation to the received signal and might therefore be slightly different each time. (resolution problem). The decoded values are the interpreted ones which are tolerant to such slight differences!
+The raw data depends on the internal state of the Arduino timer in relation to the received signal and might therefore be slightly different each time. (resolution problem).
+The decoded values are the interpreted ones which are tolerant to such slight differences!
#### Print how to send the received data:
```c++
IrReceiver.printIRSendUsage(&Serial);
```
+## Callback functionality
+Sometimes it can be difficult to call decode() periodically in the main loop to avoid missing any IR frames.
+In this case you can use the callback functionality as demonstrated in the [CallbackDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/CallbackDemo/CallbackDemo.ino#L126) example.
+This enables you to perform `resume()` and short actions independently of the state of your main loop.
+
## Ambiguous protocols
-### NEC, Extended NEC, ONKYO
+### NEC, Extended NEC, ONKYO, OpenLASIR
The **NEC protocol** is defined as 8 bit address and 8 bit command. But the physical address and data fields are each 16 bit wide.
The additional 8 bits are used to send the inverted address or command for parity checking.
The **extended NEC protocol** uses the additional 8 parity bit of address for a 16 bit address, thus disabling the parity check for address.
@@ -357,18 +320,109 @@ The decoder interprets this as a NEC 8 bit address 0x00 / 0x32 with correct pari
One way to handle this, is to force the library to **always** use the ONKYO protocol interpretation by using `#define DECODE_ONKYO`.
Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ONKYO and to revert the parity reducing manually.
+The **[OpenLASIR protocol](https://github.com/danielweidman/OpenLASIR)** is binary identical to ONKYO but has a different semantics. It is recommended to disable `#define DECODE_ONKYO` and enable `#define DECODE_OPENLASIR` when working with OpenLASIR.
+
### NEC, NEC2
On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame.
This enables an easy distinction between long presses and repeated presses and saves a bit of battery energy.
-This behavior is quite unique for NEC and its derived protocols like LG.
+This behavior is quite unique for NEC and its derived protocols like LG and Samsung.
-So there are of course also remote control systems, which uses the NEC protocol but on a long press just repeat the first frame instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
+But of course there are also remote control systems, that uses the NEC protocol but only repeat the first frame when a long press is made instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
But be careful, the NEC2 protocol can only be detected by the NEC library decoder **after** the first frame and if you do a long press!
+### Samsung, SamsungLG
+On a long press, the **SamsungLG protocol** does not repeat its frame, it sends a special short repeat frame.
+
+## RAM usage of different protocols
+The `RAW_BUFFER_LENGTH` determines the length of the **byte buffer** where the received IR timing data is stored before decoding.
+**100** is sufficient for standard protocols **up to 48 bits**, with 1 bit consisting of one mark and space.
+We always require additional 4 bytes, 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit.
+- **48** bit protocols are PANASONIC, KASEIKYO, SAMSUNG48, RC6.
+- **32** bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28), OpenLASIR require a **buffer length of 68**.
+- **16** bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) require a **buffer length of 36**.
+- MAGIQUEST requires a buffer length of **112**.
+- Air conditioners often send a longer protocol data stream **up to 750 bits**.
+
+If the record gap determined by `RECORD_GAP_MICROS` is changed from the default 8 ms to more than 20 ms, the buffer is no longer a byte but a uint16_t buffer, requiring twice as much RAM.
+
+
+## Handling unknown Protocols
+### Disclaimer
+**This library was designed to fit inside MCUs with relatively low levels of resources and was intended to work as a library together with other applications which also require some resources of the MCU to operate.**
+
+Use the **ReceiveDemo example** to print out all informations about your IR protocol.
+The **ReceiveDump example** gives you more information but has bad repeat detection due to the time required for printing the information.
+
+### Other libraries, which may cover these protocols
+#### IRMP
+If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP), which especially supports manchester protocols much better.
+
+#### IRremoteESP8266
+For **air conditioners** , you may try the [IRremoteESP8266 library](https://github.com/crankyoldgit/IRremoteESP8266), which supports an impressive set of protocols and a lot of air conditioners and works also on ESP32.
+
+#### rawirdecode and HeatpumpIR
+[Raw-IR-decoder-for-Arduino](https://github.com/ToniA/Raw-IR-decoder-for-Arduino) is not a library, but an arduino example sketch, which provides many methods of decoding especially **air conditioner** protocols. Sending of these protocols can be done by the Arduino library [HeatpumpIR](https://github.com/ToniA/arduino-heatpumpir).
+
+
+### Protocol=PULSE_DISTANCE
+If you get something like this:
+```
+PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC
+```
+then you have a code consisting of **56 bits**, which is probably from an air conditioner remote.
+You can send it with `sendPulseDistanceWidth()`.
+```c++
+uint32_t tRawData[] = { 0xB02002, 0xA010 };
+IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0);
+```
+You can send it with calling `sendPulseDistanceWidthData()` twice, once for the first 32 bit and next for the remaining 24 bits.
+The `PULSE_DISTANCE` / `PULSE_WIDTH` decoder just decodes a timing stream to a bitstream stored as hex values.
+These decoders can not put any semantics like address, command or checksum on this bitstream.
+But the bitstream is way more readable, than a timing stream. This bitstream is read **LSB first by default**.
+If LSB does not suit for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L78).
+
+**If RAM is not more than 2k, the decoder only accepts mark or space durations up to 2500 microseconds to save RAM space, otherwise it accepts durations up to 10 ms.**
+
+### Protocol=UNKNOWN
+If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as output of e.g. the ReceiveDemo example, you either have a problem with decoding a protocol, or an unsupported protocol.
+
+- If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak.
+- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby.
+- If you see timings like `+ 500,- 550 + 450,- 550 + 450,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding.
+- If you see `Protocol=UNKNOWN Hash=0x0 1 bits received` it may be that the space after the initial mark is longer than [`RECORD_GAP_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L124).
+ This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your .ino file.
+- To see more info supporting you to find the reason for your UNKNOWN protocol, you must enable the line `//#define DEBUG` in IRremoteInt.h.
+
+### How to deal with protocols not supported by IRremote
+If you do not know which protocol your IR transmitter uses, you have several choices.
+- Just use the hash value to decide which command was received. See the [SimpleReceiverForHashCodes example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino).
+- Use the [IRreceiveDemo example](examples/ReceiveDemo) or [IRreceiveDump example](examples/ReceiveDump) to dump out the IR timing.
+ You can then reproduce/send this timing with the [SendRawDemo example](examples/SendRawDemo).
+- The [IRMP AllProtocol example](https://github.com/IRMP-org/IRMP#allprotocol-example) prints the protocol and data for one of the **[40 supported protocols](https://github.com/IRMP-org/IRMP?tab=readme-ov-file#list-of-protocols)**.
+ The same library can be used to send this codes.
+- If you have a bigger Arduino board at hand (> 100 kByte program memory) you can try the
+ [IRremoteDecode example](https://github.com/bengtmartensson/Arduino-DecodeIR/blob/master/examples/IRremoteDecode/IRremoteDecode.ino) of the Arduino library [DecodeIR](https://github.com/bengtmartensson/Arduino-DecodeIR).
+- Use [IrScrutinizer](http://www.harctoolbox.org/IrScrutinizer.html).
+ It can automatically generate a send sketch for your protocol by exporting as "Arduino Raw". It supports IRremote,
+ the old [IRLib](https://github.com/cyborg5/IRLib) and [Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino).
+
+## Multiple IR receivers
+**This library now supports multiple IR receiver instances (IRrecv) per CPU** by activating `SUPPORT_MULTIPLE_RECEIVER_INSTANCES`
+and providing the simple function `UserIRReceiveTimerInterruptHandler()`.
+See the [MultipleReceivers example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/MultipleReceivers/MultipleReceivers.ino).
+
+There is also another way to use multiple receivers.
+You can connect the output pins of each IR receiver to one input pin.
+Then you can use the standard receiver object (IrReceiver).
+The IR receiver modules internally use an NPN transistor as output device with just a 30k resistor to VCC.
+This is basically an "open collector" and allows multiple output pins to be connected to one Arduino input pin.
+However, keep in mind that any weak / disturbed signal from one of the receivers will also interfere with a good signal from another receiver.
+
# Sending IR codes
-If you have a device at hand which can generate the IR codes you want to work with (aka IR remote), **it is recommended** to receive the codes with the [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino), which will tell you on the serial output how to send them.
+If you have a device at hand which can generate the IR codes you want to work with (aka IR remote),
+**it is recommended** to receive the codes with the [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino), which will tell you on the serial output how to send them.
```
Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first
@@ -377,33 +431,128 @@ Send with: IrSender.sendLG(0x2, 0x3434, );
You will discover that **the address is a constant** and the commands sometimes are sensibly grouped.
If you are uncertain about the numbers of repeats to use for sending, **3** is a good starting point. If this works, you can check lower values afterwards.
-The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**. Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
-An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols). "D" and "S" denotes device and subdevice and "F" denotes the function.
+If you have enabled `DECODE_DISTANCE_WIDTH`, the code printed by `printIRSendUsage()` **differs between 8 and 32 bit platforms**,
+so it is best to run the receiving program on the same platform as the sending program.
**All sending functions support the sending of repeats** if sensible.
Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms from start to start for NEC.
Keep in mind, that **there is no delay after the last sent mark**.
If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding.
-The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)` are kept for backward compatibility to **(old)** tutorials and unsupported as well as error prone.
+Bear in mind, that **some devices only accept commands if they are repeated one or two times**.
-## Send pin
-Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
-If `IR_SEND_PIN` is specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this macro. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library).
+Sending **old MSB codes without conversion** can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`
+or by [converting them manually to LSB](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes).
+
+## Sending UNKNOWN protocol
+If the protocol is unknown by IRremote, which often is the case for airconditioner codes,
+you can store the timing sequence in an array and send it with IrSender.sendRaw() or IrSender.sendRaw_P()
+like done in [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendDemo/SendDemo.ino#L180).
+Do not forget to send repeats.
+
+## Sending protocol from description
+If you only have the description of the protocol, but no sender which can generate the IR codes,
+then you can try to send the protocol with:
+
+```
+sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
+ uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
+ IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
+ int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = nullptr)
+```
+
+E.g. for the CDTV IR Keyboard protocol a description can be found [here](https://github.com/Korinel/Amiga-CDTV-IR-Keyboard).
+Thus, the right parameters for CDTV IR Keyboard Protocol on a 32 bit platform are:
+
+```
+sendPulseDistanceWidth(40, 9000, 4500, 1200, 400, 400, 400, , 40,
+ IRDATA_FLAGS_IS_MSB_FIRST, 110, 3); // 110 and 3 are guessed values!
+```
+
+On an 8 bit platform, you must store the 40 bits into an array of two 32 bit unsigned integers and send it with:
+
+```
+sendPulseDistanceWidthFromArray(40, 9000, 4500, 1200, 400, 400, 400, 40,
+ IRDATA_FLAGS_IS_MSB_FIRST, 110, 3); // 110 and 3 are guessed values!
+```
+
+## Sending IRDB IR codes
+The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**.
+Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function*
+is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters
+like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
+An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols).
+"D" and "S" denotes device and subdevice and "F" denotes the function.
### List of public IR code databases
http://www.harctoolbox.org/IR-resources.html
-
+## Flipper Zero codes
+The codes found in the [Flipper-IRDB database](https://github.com/Lucaslhm/Flipper-IRDB) are quite straightforward to convert, because the also use the address / command scheme.
+Protocol matching is NECext -> Onkyo, Samsung32 -> Samsung, SIRC20 -> Sony with 20 bits etc.
+
+| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) |
+|-|-|
+| Samsung32 | Samsung |
+| NEC | NEC |
+| NECext | ONKYO |
+| [\\\\\\\\\](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)
and ID is MSB of address.
address: 8A 02 20 00
command: 56 03 00 00
-> **IRremote:**
Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \\\\\\\ |
+
+## Send pin
+Any pin can be chosen as send pin as long as `IR_SEND_PIN` is **not** defined.
+This is because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
+On **ESP32** ledc channel 0 is used for generating the IR PWM.
+If `IR_SEND_PIN` is specified (as C macro), it reduces program size and improves send timing for AVR.
+If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro e.g. with `#undef IR_SEND_PIN`.
+Then you can change send pin at any time before sending an IR frame.
+See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library).
+
+## Polarity of send pin
+By default the polarity is HIGH for active and LOW for inactive or pause.
+This corresponds to the connection schema: Pin -> Resistor-> IR-LED -> Ground.
+If you want to use the connection schema: VCC -> IR-LED -> Resistor -> Pin, you must specify `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN`.
+
+## Simulate an IR receiver module for sending
+To simulate an IR receiver (such as the TSOP1738) which provides an active-low output, you only need to enable the `USE_NO_SEND_PWM` macro.
+In the case you must simulate exotic IR receivers, which provides an active-high output, you also need to enable the `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` macro.
+
+## Increase strength of sent output signal
+**The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.2 volt at 20 mA or 1.5 volt at 100 mA so you can supply up to 3 diodes with a 5 volt output.
+To power **2 diodes** with 1.2 V and 20 mA and a 5 V supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
+For **3 diodes** it requires 1.4 V / 20 mA = **70 Ω**.
+The actual current might be lower since of **loss at the AVR pin**. E.g. 0.3 V at 20 mA.
+If you do not require more current than 20 mA, there is no need to use an external transistor (at least for AVR chips).
+
+On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:.
+## Multiple IR sender instances
+**This library only supports one IR sender object (IRsend) per CPU.**
+However since sending is a serial task, you can use `setSendPin()` to switch the pin to send, thus emulating multiple sender.
+
+
# Tiny NEC receiver and sender
-For applications only requiring NEC or FAST -see below- protocol, there is a special receiver / sender included,
+For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
which has very **small code size of 500 bytes and does NOT require any timer**.
-Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote#irdispatcherdemo) examples.
+## Principle of operation
+Unlike IRremote, which samples the input every 50 µs, the TinyIRReceiver uses a **pin change interrupt** for on-the-fly decoding.
+This restricts the range of protocols that can be recognised.
+On each level change, the level and the time since the last change are used to incrementally decode the protocol.
+With this operating principle, we **cannot wait for a timeout** and then decode the protocol as IRremote does.
+Instead, we need to know which is the last bit (level change) of a protocol in order to perform the final decoding
+and call of the optional **user-provided callback function** `handleReceivedTinyIRData()`.
+This means that **we need to know the number of bits in a protocol** and therefore the protocol family in order to decode successfully.
+
+For each complete IR frame/command received, the decoded data is copied to the `TinyIRReceiverData` structure
+and the user-provided `handleReceivedTinyIRData()` function is called in an interrupt context.
+However, **interrupts are explicitly enabled here** to allow the use of delay() and millis() etc.
+
+Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`.
+The **TinyIRSender** generates its 38 kHz PWM signal by **[software bit banging](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/TinyIRSender.hpp#L68)** using the `delayMicroseconds()` and `micros()` functions.
+
### TinyIRReceiver usage
```c++
//#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.
@@ -411,15 +560,14 @@ Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRre
#include "TinyIRReceiver.hpp"
void setup() {
- initPCIInterruptForTinyReceiver(); // Enables the interrupt generation on change of IR input signal
+ initPCIInterruptForTinyIRReceiver(); // Enables the interrupt generation on change of IR input signal
}
-void loop() {}
-
-// This is the function, which is called if a complete command was received
-// It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here
-void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) {
- printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags);
+void loop() {
+ if (TinyIRReceiverDecode()) {
+ printTinyIRReceiverResultMinimal(&Serial);
+ }
+ // No resume() required :-)
}
```
@@ -428,13 +576,13 @@ void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags
#include "TinyIRSender.hpp"
void setup() {
- sendNECMinimal(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats.
+ sendNEC(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats.
}
void loop() {}
```
-Another tiny receiver and sender **supporting more protocols** can be found [here](https://github.com/LuisMiCa/IRsmallDecoder).
+Another tiny receiver **supporting more protocols** can be found [here](https://github.com/LuisMiCa/IRsmallDecoder).
# The FAST protocol
The FAST protocol is a proprietary modified JVC protocol **without address, with parity and with a shorter header**.
@@ -475,174 +623,227 @@ void loop() {}
The FAST protocol can be received by IRremote and TinyIRReceiver.
+# Feedback LED
+The feedback LED output is enabled by default. This means that **the LED is on when we receive or send a mark**.
+The feedback LED code can be completely removed at compile time using the following macros:
+- `NO_LED_RECEIVE_FEEDBACK_CODE` for receiving
+- `NO_LED_SEND_FEEDBACK_CODE` for sending
+- `NO_LED_FEEDBACK_CODE` for receiving and sending
+
+### Receiving
+For receiving, feedback LED can be activated or deactivated programmatically by `enableLEDFeedback()`, `disableLEDFeedback()` or `setLEDFeedback(bool aEnableLEDFeedback)`.
+The starting value is set by the second parameter of `begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)`. You can use the macros `ENABLE_LED_FEEDBACK` and `DISABLE_LED_FEEDBACK` for the second parameter.
+
+### Sending
+LED feedback is **always enabled** when sending and cannot be deactivated programmatically.
+It can only be deactivated at compile time.
+
+# IRCommandDispatcher class
+If you want to **handle many IR commands** in a structured way, you can use a big **switch statement**, or use the class `IRCommandDispatcher`.
+The IRCommandDispatcher class receives IR commands and maps them to different functions by means of a mapping array `IRMapping[]`.
+
+By default, every mapped command is **blocking**. However it can be declared as **non-blocking** and / or **repeatable**.
+Non-blocking commands are executed immediately, blocking commands are executed if no other command is just running.
+If another blocking command is currently running, a **request to stop** is set
+and the command is stored for the main loop to be executed by `checkAndRunSuspendedBlockingCommands()`.
+The request to stop must be checked by any blocking function using the macros `DELAY_AND_RETURN_IF_STOP()`, `RETURN_IF_STOP`, `BREAK_IF_STOP` and `IS_STOP_REQUESTED`.
+Only commands that are marked as **repeatable** will be exectuted when a IR repeat frame is received.
+Therefore this only makes sense for non-blocking comands :-).
+
+Code snippets are from [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo).
+
+```c++
+// IR code mapping which is useful if more than one remote is supported
+#define IR_0 0x19
+#define IR_HASH 0x0D
+#define COMMAND_BLINK IR_0
+#define COMMAND_STOP IR_HASH
+
+// Strings of commands for Serial output
+static const char blink20times[] PROGMEM ="blink 20 times";
+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
+ */
+{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 },
+...
+/*
+ * Repeatable short commands
+ */
+{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink },
+...
+
+/*
+ * 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);
+ }
+}
+// Other useful macros are RETURN_IF_STOP, BREAK_IF_STOP and IS_STOP_REQUESTED.
+```
+
+Examples of mapping arrays can be found in the [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/DemoIRCommandMapping.h#L185), for [QuadrupedControl](https://github.com/ArminJo/QuadrupedControl/blob/master/examples/QuadrupedControl/QuadrupedIRCommandMapping.h#L445), for [RobotArmControl](https://github.com/ArminJo/RobotArmControl/blob/master/RobotArmControl/RobotArmIRCommandMapping.h#L320) or for [4 WD RobotCar control](https://github.com/ArminJo/PWMMotorControl/blob/master/examples/IRDispatcherControl/RobotCarIRCommandMapping.h#L308)
+
+
+
+
# FAQ and hints
+## Receiving stops after analogWrite() or tone() or after running a motor
+The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
+On some boards where a software timer is available, the software timer is used.
+Be aware that the hardware timer used for receiving should not be used for `analogWrite()`.
+Especially **motor** control often uses the `analogWrite()` function and will therefore stop the receiving if used on the pins indicated [here](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
+On the Uno and other AVR boards the receiver timer ist the same as the tone timer. Thus receiving will stop after a `tone()` command.
+See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`.
+
+## Receiving sets overflow flag
+The flag `IRDATA_FLAGS_WAS_OVERFLOW` is set, if `RAW_BUFFER_LENGTH` is too small for all the marks and spaces of the protocol.
+This can happen on long protocol frames like the ones from air conditioner.
+It also can happen, if `RECORD_GAP_MICROS` is smaller than the real gap between a frame and the repetition frame, thus interpreting both as one consecutive frame.
+Best is to dump the timing then, to see which reason holds.
## Problems with Neopixels, FastLed etc.
IRremote will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 µs).
-Whether you use the Adafruit Neopixel lib, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs.
-In turn, this stops the IR interrupt handler from running when it needs to. See also this [video](https://www.youtube.com/watch?v=62-nEJtm070).
+Whether you use the Adafruit Neopixel library, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs.
+In turn, this stops the IR interrupt handler from sampling the IR signal.
+
+Each WS2812 LED requires 30 µs at **800 kHz**, an **8 pixel** strip requires 240 µs and therefore **skips 4 samples** of the IR signal, which is sampled each 50 µs.
+For example, the standard timing for the NEC protocol is 560 µs or 11 samples. However, with a loss of four samples, however, we **exceed the accepted 25 %** decoding deviation threshold.
One **workaround** is to wait for the IR receiver to be idle before you send the Neopixel data with `if (IrReceiver.isIdle()) { strip.show();}`.
-This **prevents at least breaking a running IR transmission** and -depending of the update rate of the Neopixel- may work quite well.
-There are some other solutions to this on more powerful processors,
+This **prevents a running IR transmission from beeing broken**, and depending on the update rate of the Neopixel, it may work quite well.
+There are some other solutions to this on **more powerful CPU's**,
[see this page from Marc MERLIN](http://marc.merlins.org/perso/arduino/post_2017-04-03_Arduino-328P-Uno-Teensy3_1-ESP8266-ESP32-IR-and-Neopixels.html)
## Does not work/compile with another library
**Another library is only working/compiling** if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.
-This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage).
-
-## Multiple IR receivers
-IRreceiver consists of one timer triggered function reading the digital IR signal value from one pin every 50 µs.
-So **multiple IR receivers** can only be used by connecting the output pins of several IR receivers together.
-The IR receivers use an NPN transistor as output device with just a 30k resistor to VCC.
-This is almost "open collector" and allows connecting of several output pins to one Arduino input pin.
-But keep in mind, that any weak / disturbed signal from one of the receivers will in turn also disturb a good signal from another one.
-
-## Increase strength of sent output signal
-**The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.2 volt at 20 mA or 1.5 volt at 100 mA so you can supply up to 3 diodes with a 5 volt output.
-To power **2 diodes** with 1.2 V and 20 mA and a 5 V supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
-For **3 diodes** it requires 1.4 V / 20 mA = **70 Ω**.
-The actual current might be lower since of **loss at the AVR pin**. E.g. 0.3 V at 20 mA.
-If you do not require more current than 20 mA, there is no need to use an external transistor (at least for AVR chips).
-
-On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:.
+This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
## Minimal CPU clock frequency
For receiving, the **minimal CPU clock frequency is 4 MHz**, since the 50 µs timer ISR (Interrupt Service Routine) takes around 12 µs on a 16 MHz ATmega.
-The TinyReceiver, which reqires no polling, runs with 1 MHz.
-For sending, the **default software generated PWM has problems on AVR running with 8 MHz**. The PWM frequency is around 30 instead of 38 kHz and RC6 is not reliable. You can switch to timer PWM generation by `#define SEND_PWM_BY_TIMER`.
+The TinyIRReceiver, which requires no polling, works down to 1 MHz.
+For sending, the **minimal CPU clock frequency for software generated PWM is 8 MHz**.
+You can switch to timer and hardware PWM generation at fixed pins by `#define SEND_PWM_BY_TIMER`.
+### Hardware PWM generation of sending signal with 8 bit timer
+- 16 MHZ F_CPU and 38 kHz -> prescaling = 2, divider = 210.526 -> 38.1 kHz with divider 210
+- 8 MHZ F_CPU and 38 kHz -> no prescaling , divider = 210.526 -> 38.1 kHz with divider 210
+- 4 MHZ F_CPU and 38 kHz -> no prescaling , divider = 105.26 -> 38.1 kHz with divider 105
+- 1 MHZ F_CPU and 38 kHz -> no prescaling , divider = 26.31 -> 38.4 kHz with divider 36
+TinyIRSender does not support hardware PWM generation.
## Bang & Olufsen protocol
The Bang & Olufsen protocol decoder is not enabled by default, i.e if no protocol is enabled explicitly by #define `DECODE_`. It must always be enabled explicitly by `#define DECODE_BEO`.
This is because it has an **IR transmit frequency of 455 kHz** and therefore requires a different receiver hardware (TSOP7000).
And because **generating a 455 kHz PWM signal is currently only implemented for `SEND_PWM_BY_TIMER`**, sending only works if `SEND_PWM_BY_TIMER` or `USE_NO_SEND_PWM` is defined.
-For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L44).
-
-# Handling unknown Protocols
-## Disclaimer
-**This library was designed to fit inside MCUs with relatively low levels of resources and was intended to work as a library together with other applications which also require some resources of the MCU to operate.**
-
-For **air conditioners** [see this fork](https://github.com/crankyoldgit/IRremoteESP8266), which supports an impressive set of protocols and a lot of air conditioners.
-
-For **long signals** see the blog entry: ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino).
-
-
-## Protocol=PULSE_DISTANCE
-If you get something like this:
-```
-PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC
-```
-then you have a code consisting of **56 bits**, which is probably from an air conditioner remote.
-You can send it with sendPulseDistance().
-```c++
-uint32_t tRawData[] = { 0xB02002, 0xA010 };
-IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0);
-```
-You can send it with calling sendPulseDistanceWidthData() twice, once for the first 32 bit and next for the remaining 24 bits.
-**The PulseDistance or PulseWidth decoders just decode a timing steam to a bit stream**.
-They can not put any semantics like address, command or checksum on this bitstream, since it is no known protocol.
-But the bitstream is way more readable, than a timing stream. This bitstream is read **LSB first by default**.
-If this does not suit you for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L48).
-
-## Protocol=UNKNOWN
-If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as output of e.g. the ReceiveDemo example, you either have a problem with decoding a protocol, or an unsupported protocol.
-
-- If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak.
-- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby.
-- If you see timings like `+ 500,- 550 + 450,- 550 + 500,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding.
-- If you see `Protocol=UNKNOWN Hash=0x0 1 bits received` it may be that the space after the initial mark is longer than [`RECORD_GAP_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L124).
- This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your .ino file.
-- To see more info supporting you to find the reason for your UNKNOWN protocol, you must enable the line `//#define DEBUG` in IRremoteInt.h.
-
-## How to deal with protocols not supported by IRremote
-If you do not know which protocol your IR transmitter uses, you have several choices.
-- Use the [IRreceiveDump example](examples/ReceiveDump) to dump out the IR timing.
- You can then reproduce/send this timing with the [SendRawDemo example](examples/SendRawDemo).
- For **long codes** with more than 48 bits like from air conditioners, you can **change the length of the input buffer** in [IRremote.h](src/IRremoteInt.h#L36).
-- The [IRMP AllProtocol example](https://github.com/IRMP-org/IRMP#allprotocol-example) prints the protocol and data for one of the **40 supported protocols**.
- The same library can be used to send this codes.
-- If you have a bigger Arduino board at hand (> 100 kByte program memory) you can try the
- [IRremoteDecode example](https://github.com/bengtmartensson/Arduino-DecodeIR/blob/master/examples/IRremoteDecode/IRremoteDecode.ino) of the Arduino library [DecodeIR](https://github.com/bengtmartensson/Arduino-DecodeIR).
-- Use [IrScrutinizer](http://www.harctoolbox.org/IrScrutinizer.html).
- It can automatically generate a send sketch for your protocol by exporting as "Arduino Raw". It supports IRremote,
- the old [IRLib](https://github.com/cyborg5/IRLib) and [Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino).
-
-
+For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L46).
# Examples for this library
-The examples are available at File > Examples > Examples from Custom Libraries / IRremote.
- 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.
+These examples can be found in the Arduino IDE under File > Examples > Examples from Custom Libraries / IRremote.
+**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.**
+See also [DroneBot Workshop SimpleReceiver](https://dronebotworkshop.com/ir-remotes/#SimpleReceiver_Example_Code) and [SimpleSender](https://dronebotworkshop.com/ir-remotes/#SimpleSender_Example_Code).
-#### SimpleReceiver + SimpleSender
-The **[SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** and **[SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)** examples are a good starting point.
+### [SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino) + [SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)
+The **SimpleReceiver** and **SimpleSender** examples are a good starting point.
A simple example can be tested online with [WOKWI](https://wokwi.com/projects/338611596994544210).
-#### TinyReceiver + TinySender
+### [SimpleReceiverForHashCodes](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino)
+The **SimpleReceiverForHashCodes** uses only the hash decoder.
+It converts all IR frames longer than 6 to a 32 bit hash code, thus enabling receiving of unknown protocols.
+See: http://www.righto.com/2010/01/using-arbitrary-remotes-with-arduino.html
+
+### [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino) + [TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)
If **code size** or **timer usage** matters, look at these examples.
-The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
+The **TinyReceiver** example uses the **TinyIRReceiver** library
+which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**.
+They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
-The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
-It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example.
+The **TinySender** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
+It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example. It has options to send using Extended NEC, ONKYO and FAST protocols.
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).
-#### SmallReceiver
+### [SmallReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino)
If the protocol is not NEC and code size matters, look at this [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SmallReceiver/SmallReceiver.ino).
-#### ReceiveDemo + AllProtocolsOnLCD
-[ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.
+### [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) + [AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino)
+ReceiveDemo receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.
Long press of one IR button (receiving of multiple repeats for one command) is detected.
-[AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino) additionally **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).
+AllProtocolsOnLCD additionally **displays the short result on a 1602 LCD**.
+The LCD can be connected parallel or serial (I2C).
By connecting debug pin to ground, you can force printing of the raw values for each frame. The pin number of the debug pin is printed during setup, because it depends on board and LCD connection type.
This example also serves as an **example how to use IRremote and tone() together**.
-#### ReceiveDump
-Receives all protocols and dumps the received signal in different flavors including Pronto format. Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN.
+#### [ReceiveDump](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDump/ReceiveDump.ino)
+Receives all protocols and dumps the received signal in different flavors including **Pronto format**.
+Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN.
-#### SendDemo
+#### [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendDemo/SendDemo.ino)
Sends all available protocols at least once.
-#### SendAndReceive
+#### [MultipleSendPins](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/MultipleSendPins/MultipleSendPins.ino)
+Demonstrates sending IR codes toggling between 2 **different send pins**.
+
+#### [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino)
Demonstrates **receiving while sending**.
-#### ReceiveAndSend
-Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the approriate protocol encoder. `UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`.
+#### [ReceiveAndSend](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSend/ReceiveAndSend.ino)
+Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the appropriate protocol encoder.
+`UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`.
-#### ReceiveAndSendDistanceWidth
+#### [ReceiveAndSendDistanceWidth](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino)
Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.
+If RAM is not more than 2k, the decoder only accepts mark or space durations up to 2500 microseconds to save RAM space, otherwise it accepts durations up to 10 ms.
Storing data for distance width protocol requires 17 bytes.
The ReceiveAndSend example requires 16 bytes for known protocol data and 37 bytes for raw data of e.g.NEC protocol.
-#### ReceiveOneAndSendMultiple
+#### [ReceiveOneAndSendMultiple](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino)
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.
-#### IRDispatcherDemo
-Framework for **calling different functions of your program** for different IR codes.
+#### [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/IRDispatcherDemo.ino)
+**Calling different functions** of your program for different IR codes.
-#### IRrelay
+#### [ControlRelay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ControlRelay/ControlRelay.ino)
**Control a relay** (connected to an output pin) with your remote.
-#### IRremoteExtensionTest
-[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino) for a user defined class, which itself uses the IRrecv class from IRremote.
+#### [IRremoteExtensionTest](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino)
+Example for a user defined class, which itself uses the IRrecv class from IRremote.
-#### SendLGAirConditionerDemo
-[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino) for sending LG air conditioner IR codes controlled by Serial input.
+#### [SendLGAirConditionerDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino)
+Example for sending LG air conditioner IR codes controlled by Serial input.
By just using the function `bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter)` you can control the air conditioner by any other command source.
The file *acLG.h* contains the command documentation of the LG air conditioner IR protocol. Based on reverse engineering of the LG AKB73315611 remote.

IReceiverTimingAnalysis can be tested online with [WOKWI](https://wokwi.com/projects/299033930562011656)
Click on the receiver while simulation is running to specify individual IR codes.
-#### ReceiverTimingAnalysis
-This [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino) analyzes the signal delivered by your IR receiver module.
+#### [ReceiveAndSendHob2Hood](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino)
+Example for receiving and sending AEG / Elektrolux Hob2Hood protocol.
+
+#### [ReceiverTimingAnalysis](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino)
+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 NEC IR codes.
-#### UnitTest
+#### [UnitTest](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/UnitTest/UnitTest.ino)
ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**.
+Here you see the delay of the receiver output (blue) from the IR diode input (yellow).
+
# WOKWI online examples
- [Simple receiver](https://wokwi.com/projects/338611596994544210)
@@ -651,57 +852,88 @@ ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**.
- [ReceiverTimingAnalysis](https://wokwi.com/projects/299033930562011656)
- [Receiver with LCD output and switch statement](https://wokwi.com/projects/298934082074575369)
+# IR control of a robot car
+This [example](https://github.com/ArminJo/PWMMotorControl?tab=readme-ov-file#basicircontrol) of the **Arduino PWMMotorControl library** controls the basic functions of a robot car using the IRremote library.
+It controls 2 PWM motor channels, 2 motors at each channel.
+[Here](https://www.instructables.com/Arduino-4WD-Car-Assembly-and-Code-With-Optional-In/) you can find the instructable for car assembly and code.
+
+IR_RobotCar with TL1838 IR receiver plugged into expansion board.
+
+
# Issues and discussions
- Do not open an issue without first testing some of the examples!
- If you have a problem, please post the MCVE (Minimal Complete Verifiable Example) showing this problem. My experience is, that most of the times you will find the problem while creating this MCVE :smile:.
-- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us help you when we can read your code!**
+- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us to help you when we can read your code!**
-# Compile options / macros for this library
+# Compile options / macros for IRremote
To customize the library to different requirements, there are some compile options / macros available.
These macros must be defined in your program **before** the line `#include ` to take effect.
Modify them by enabling / disabling them, or change the values if applicable.
| Name | Default value | Description |
-|:---|---:|----|
-| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. |
-| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. |
-| `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) |
-| `DECODE_STRICT_CHECKS` | disabled | Check for additional characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. |
+|-|-:|-|
+| `RAW_BUFFER_LENGTH` | 200 | Buffer size of raw input uint16_t buffer. Must be even! If it is too small, overflow flag will be set. 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. A value of 200 requires 200 bytes RAM. |
+| `USE_16_BIT_TIMING_BUFFER` | disabled | Use a 16-bit buffer if raw timing capture is required and exact values above 12750 us must be preserved. This doubles the RAM size of the buffer. |
+| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance width protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. |
+| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST LEGO_PF, and OpenLASIR from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
+| `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) |
+| `USE_THRESHOLD_DECODER` | disabled | If enabled, may give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses and forces value of MARK_EXCESS_MICROS to 0 to save program memory. Requires up to additional 120 bytes program memory. |
+| `USE_STRICT_DECODER` | disabled | Check for all 4 one and zero protocol timings. Only sensible for development or very exotic requirements. Requires up to 300 additional bytes of program memory. |
| `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. |
-| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. |
-| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
-| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. |
-| `IR_SEND_PIN` | disabled | If specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. |
-| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). |
-| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
-| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
-| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! |
-| `DISABLE_CODE_FOR_RECEIVER` | disabled | Saves up to 450 bytes program memory and 269 bytes RAM if receiving functionality is not required. |
-| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
-| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. |
-| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. |
-| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. |
-| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` | 25 | Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. |
+| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. Is set to 20 if `DO_NOT_USE_THRESHOLD_DECODER` is enabled. |
+| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
+| `DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE` | 50 if RAM <= 2k, else 200 | A value of 200 allows to decode mark or space durations up to 10 ms. |
+| `SHOW_DISTANCE_WIDTH_DECODER_ERRORS` | disabled | Prints the reason which prevents data to be decoded as distance width data. |
+| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. |
+| `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. |
+| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the **advantage of more exact PWM generation**, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the **disadvantage of using a hardware timer**, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM generation for each pin without using a shared resource (timer). |
+| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
+| `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverses the polarity of space level for PWM at the send pin, i.e. space is high. Can be used to connect IR LED between VCC and the send pin. It is like open drain but with electrical active high in its logical inactive state. |
+| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode for PWM at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! |
+| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
+| `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` | disabled | Only evaluated if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. |
+| `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. |
+| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. |
+| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. |
+| `NO_LED_RECEIVE_FEEDBACK_CODE` | disabled | Disables the LED feedback code for receive. Saves around 100 bytes program memory for receiving and halving the receiver ISR (Interrupt Service Routine) processing time. |
+| `NO_LED_SEND_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send. Saves around 322 bytes for sending. |
+| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. |
+| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT` | 25 | Relative tolerance for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. |
| `DEBUG` | disabled | Enables lots of lovely debug output. |
| `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. |
-These next macros for **TinyIRReceiver** must be defined in your program before the line `#include ` to take effect.
+# Macros for TinyIR
+These macros 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_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. Not used in IRremote. |
| `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. |
-| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. |
-| `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. |
-| `USE_ONKYO_PROTOCOL` | disabled | 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. |
+| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED code for send and receive. Saves 14 bytes program memory. |
+| `NO_LED_RECEIVE_FEEDBACK_CODE` | disabled | Disables the LED feedback code for receive. |
+| `NO_LED_SEND_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send. |
+| `DISABLE_PARITY_CHECKS` | disabled | Disables the address and command parity checks. Saves 48 bytes program memory. |
+| `USE_EXTENDED_NEC_PROTOCOL` | disabled | 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` | disabled | 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` | disabled | 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` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. |
+| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the user provided function `void handleReceivedTinyIRData()` each time a frame or repeat is received. |
+
+
-The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect.
-| `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. |
+# Macros for IRCommandDispatcher
+These macros must be defined in your program before the line `#include ` to take effect.
+| Name | Default value | Description |
+|-|-:|-|
+| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyIRReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. |
+| `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | 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. |
+| `IR_ADDRESS` | empty | If set, compare the address returned by the IR library with this value before executing a command. |
+| `DISPATCHER_BUZZER_FEEDBACK_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. |
+| `USE_DISPATCHER_COMMAND_STRINGS` | disabled | Enables 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. |
+
+
### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.
@@ -721,9 +953,14 @@ If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easi
# Supported Boards
**Issues and discussions with the content "Is it possible to use this library with the ATTinyXYZ? / board XYZ" without any reasonable explanations will be immediately closed without further notice.**
+For **ESP8266/ESP32**, [the IRremoteESP8266 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 CPU's are tested with the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) library**.
-ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board.
+Digispark boards are tested only with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using the `New Style` pin mapping for the Digispark Pro board.
+**ATtiny boards** are tested only with **[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore)**.
+
- Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc.
+- Arduino Uno R4, but not yet tested, because of lack of a R4 board. **Sending does not work** on the `arduino:renesas_uno:unor4wifi`.
- Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 3.2 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team)
- Sanguino
- ATmega8, 48, 88, 168, 328
@@ -732,15 +969,15 @@ ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](ht
- ATmega4809 (Nano every)
- ATtiny3217 (Tiny Core 32 Dev Board)
- ATtiny84, 85, 167 (Digispark + Digispark Pro)
-- SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**)
+- SAMD (Zero, MKR*, **but not DUE, the latter is SAM architecture**)
- ESP8266
-- ESP32 (ESP32 C3 since board package 2.0.2 from Espressif)
+- ESP32, ESP32-C3 since board package 2.0.2 from Espressif. Other CPUs are not tested! SP32-S3 is not supported (yet).
- Sparkfun Pro Micro
- Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE
- BluePill with STM32
- RP2040 based boards (Raspberry Pi Pico, Nano RP2040 Connect etc.)
+- Indian VEGA RISC-V boards - not tested
-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)
We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side.
If you can provide **examples of using a periodic timer for interrupts** for the new board, and the board name for selection in the Arduino IDE, then you have way better chances to get your board supported by IRremote.
@@ -749,44 +986,51 @@ If you can provide **examples of using a periodic timer for interrupts** for the
# Timer and pin usage
The **receiver sample interval of 50 µs is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used.
-Every pin can be used for receiving.
+On **ESP8266** `timer1` is used for receive interrupts, which makes it incompatible to the Servo and other libraries.
+On **ESP32** `hw_timer_t` is used for receive interrupts.
+
+Every pin can be used for receiving.
+If software PWM is selected, which is default, every pin can also be used for sending. Sending with software PWM does not require a timer!
The TinyReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer** and runs even on a 1 MHz ATtiny85.
-The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). It can be adjusted here.
+The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). The selected timer can be adjusted here.
+
**Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.
-| Board/CPU | Receive
& PWM Timers| Hardware-PWM Pin | analogWrite()
pins occupied by timer |
-|--------------------------------------------------------------------------|-------------------|---------------------|-----------------------|
-| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **1** | **6** |
-| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **0**, 1 | **0**, 4 | **0**, 1 & 4 |
-| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** |
-| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **9**, 8 - 15 | **8 - 15** |
-| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore) | **TCB0** | **PA05** |
-| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore) | **TCA0** | **PA3** |
-| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore) | **TCA0**, TCD | % |
-| [ATmega8](https://github.com/MCUdude/MiniCore) | **1** | **9** |
+| Board/CPU | Receive
& send PWM Timer
Default timer is **bold** | Hardware-Send-PWM Pin | analogWrite()
pins occupied by timer |
+|-|-|-|-|
+| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x4.md) | **1** | **6** | |
+| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x5.md) | **0**, 1 | **0**, 4 | **0**, 1 & 4 |
+| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x8.md) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** |
+| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x7.md) | **1** | **9**, 8 - 15 | **8 - 15** |
+| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x04.md) | **TCB0** | **PA05** |
+| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md) | **TCA0** | **PA3** |
+| [ATtiny1624](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x24.md) | **TCA0** | **PA3** |
+| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x17.md) | **TCA0**, TCD | % |
+| [ATmega8](https://github.com/MCUdude/MiniCore#supported-microcontrollers) | **1** | **9** |
+| [ATmega1284](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2**, 3 | 13, 14, 6 |
+| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2** | 13, **14** |
+| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | **1** | **13** |
+| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore#supported-microcontrollers) | **1** | **13** |
+| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore#pinout ) | **1** | **13** |
| ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** |
-| [ATmega1284](https://github.com/MCUdude/MightyCore) | 1, **2**, 3 | 13, 14, 6 |
-| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 1, **2** | 13, **14** |
-| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **1** | **13** |
-| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore) | **1** | **13** |
-| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore) | **1** | **13** |
-| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 |
-| ATmega4809 | **TCB0** | **A4** |
-| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 |
-| Zero (SAMD) | **TC3** | \*, **9** |
-| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins |
-| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 |
+| ATmega1280, **ATmega2560** | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | 5, 6, **9**, 11, 46 |
+| ATmega4809 | **TCB0** | **A4** | |
+| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 |
+| Zero (SAMD) | **TC3** | \*, **9** | |
+| [ESP8266](http://esp8266.net/) | **timer1** | % | |
+| [ESP32](http://esp32.net/) | **hw_timer_t**
**Ledc channel 0** | All pins | |
+| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | |
| [Teensy 1.0](https://www.pjrc.com/teensy/pinout.html) | **1** | **17** | 15, 18 |
| [Teensy 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, 3, **4_HS** | 9, **10**, 14 | 12 |
| [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, **2**, 3 | **1**, 16, 25 | 0 |
| [Teensy-LC](https://www.pjrc.com/teensy/pinout.html) | **TPM1** | **16** | 17 |
-| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** |
+| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | |
| [Teensy 4.0 - 4.1](https://www.pjrc.com/teensy/pinout.html) | **FlexPWM1.3** | **8** | 7, 25 |
-| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** |
+| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** |
| [BluePill / STM32F103C8T6](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill) | **TIM4** | % | **PB6 & PB7 & PB8 & PB9** |
-| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin |
+| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://www.raspberrypi.com/documentation/pico-sdk/high_level.html#group_alarm_1ga40b4a03bf9e967d4e7170d20c5c9fb15) | All pins | No pin |
| [RP2040 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin |
### No timer required for sending
@@ -803,8 +1047,11 @@ Since the Arduino `micros()` function has a resolution of 4 µs at 16 MHz,
## Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()
If you use a library which requires the same timer as IRremote, you have a problem, since **the timer resource cannot be shared simultaneously** by both libraries.
+### Use NEC protocol and TinyIRReceiver
+[TinyIRReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) does not require a timer, it relies on interrupts, thus avoiding any timer resource problems.
+
### Change timer
-The best approach is to change the timer used for IRremote, which can be accomplished by specifying the timer before `#include `.
+The best approach is to **change the timer** used for IRremote, which can be accomplished by specifying the timer before `#include `.
The timer specifications available for your board can be found in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp).
```c++
@@ -821,23 +1068,29 @@ The timer specifications available for your board can be found in [private/IRTim
Here you see the Arduino Mega board and the available specifications are `IR_USE_AVR_TIMER[1,2,3,4,5]`.
You **just have to include a line** e.g. `#define IR_USE_AVR_TIMER3` before `#include ` to enable timer 3.
-But be aware that the new timer in turn might be incompatible with other libraries or commands.
-For other boards/platforms you must look for the appropriate section guarded by e.g. `#elif defined(ESP32)`.
+But be aware that the new timer in turn might be again incompatible with other libraries or Arduino functions.
+For non AVR boards/platforms you must look for the appropriate section guarded by e.g. `#elif defined(ESP32)`.
### Stop and start timer
Another approach can be to share the timer **sequentially** if their functionality is used only for a short period of time like for the **Arduino tone() command**.
-An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), where the timer settings for IR receive are restored after the tone has stopped.
-For this we must call `IrReceiver.start()` or better `IrReceiver.start(microsecondsOfToneDuration)`.
-This only works since each call to` tone()` completely initializes the timer 2 used by the `tone()` command.
+An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298), where the IR timer is restarted after the tone has stopped.
+
+```c++
+IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
+tone(TONE_PIN, 2200, 8);
+delay(8);
+IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
+```
+This works on AVR boards like Uno because each call to` tone()` completely initializes the timer 2 used by the `tone()` command.
## Hardware-PWM signal generation for sending
If you define `SEND_PWM_BY_TIMER`, the send PWM signal is forced to be generated by a hardware timer on most platforms.
By default, the same timer as for the receiver is used.
Since each hardware timer has its dedicated output pin(s), you must change timer or timer sub-specifications to change PWM output pin. See [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp)
-**Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/39bdf8d7bf5b90dc221f8ae9fb3efed9f0a8a1db/examples/SimpleSender/PinDefinitionsAndMore.h#L273), where **PWM generation does not require a timer**.
+**Exceptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/PinDefinitionsAndMore.h#L341), where **PWM generation does not require a timer**.
## Why do we use 30% duty cycle for sending
-We do it according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf):
+We [do it](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRSend.hpp#L1194) according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf):
- Carrier duty cycle 50 %, peak current of emitter IF = 200 mA, the resulting transmission distance is 25 m.
- Carrier duty cycle 10 %, peak current of emitter IF = 800 mA, the resulting transmission distance is 29 m. - Factor 1.16
The reason is, that it is not the pure energy of the fundamental which is responsible for the receiver to detect a signal.
@@ -848,11 +1101,14 @@ Due to automatic gain control and other bias effects, high intensity of the 38 k
# How we decode signals
The IR signal is sampled at a **50 µs interval**. For a constant 525 µs pulse or pause we therefore get 10 or 11 samples, each with 50% probability.
And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
-Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
-E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
-And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value]/https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown)
-to compensate for this receiver (and signal strength as well as ambient light dependent :disappointed: ) specific deviation.
-Welcome to the world of **real world signal processing**.
+Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L469-L491).
+E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0.
+This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space.
+For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
+And since the receivers generated marks are longer or shorter than the spaces,
+we have introduced the [`MARK_EXCESS_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) macro
+to compensate for this receiver and signal strength as well as ambient light dependent :disappointed: specific deviation.
+**Welcome to the world of real world signal processing**.
@@ -866,16 +1122,16 @@ Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.
# Quick comparison of 5 Arduino IR receiving libraries
-[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)**.
-
**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**. If you have complains about the data or request for extensions, please send a PM or open a discussion.
+I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR library 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) | [Minimal NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
-|---------|------|-----------|--------|----------|----------|----------|
-| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC | NEC + RC5 + Sony + Samsung |
+| 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 | % |
@@ -887,30 +1143,37 @@ It is dated from **24.06.2022**. If you have complains about the data or request
| 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 | 6/2022 | 4/2018 | 3/2022 | 6/2022 | 6/2022 | 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 - 45 issues, no reaction for at least one year.** | Universal decoder and encoder.
Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. |
+| 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
+# [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md)
+
# Useful links
+- [Online NEC to Pronto converting tool](https://www.yamaha.com/ypab/irhex_converter.asp)
- [List of public IR code databases](http://www.harctoolbox.org/IR-resources.html)
- [LIRC database](http://lirc-remotes.sourceforge.net/remotes-table.html)
- [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols)
- [IRDB database for IR codes](https://github.com/probonopd/irdb/tree/master/codes)
- [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols)
+- [Good introduction to IR remotes by DroneBot Workshop](https://dronebotworkshop.com/ir-remotes/)
- [IR Remote Control Theory and some protocols (upper right hamburger icon)](https://www.sbprojects.net/knowledge/ir/)
-- [Interpreting Decoded IR Signals (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html)
+- [Overviev of many protocols](https://www.hifi-remote.com/wiki/index.php/Category:DecodeIR)
+- [Overviev of many protocols on one page (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html)
- ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino)
- The original blog post of Ken Shirriff [A Multi-Protocol Infrared Remote Library for the Arduino](http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html)
- [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf)
+# [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md)
+
# License
Up to the version 2.7.0, the License is GPLv2.
From the version 2.8.0, the license is the MIT license.
# Copyright
Initially coded 2009 Ken Shirriff http://www.righto.com
-Copyright (c) 2016-2017 Rafi Khan
-Copyright (c) 2020-2023 [Armin Joachimsmeyer](https://github.com/ArminJo)
+Copyright (c) 2016-2017 Rafi Khan https://rafikhan.io
+Copyright (c) 2020-2025 [Armin Joachimsmeyer](https://github.com/ArminJo)
diff --git a/changelog.md b/changelog.md
index 748f7e2bf..c20528f30 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,19 +2,128 @@
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
+# 4.7.1
+- Changed wrong &Serial to aSerial at 2 places.
+
+# 4.7.0
+- Added removed typedef `IRRawDataType` for backward compatibility.
+- Modified and renamed function `setToggleBitValueForRC5AndRC6()` to `setNextToggleBitValueForRC5AndRC6()`.
+- Fixed bug in sending RC6A.
+- Updated `LG` protocol and removed useless `LG2` protocol.
+- Added new functions `match*WithGreaterRange()`, e.g. `matchMarkWithGreaterRange()`.
+- Improved B&O decoding using new functions.
+
+# 4.6.1
+- Fixed bug #1347 in RC5/RC6 autorepeat bit handling. Thanks to Craig Leres.
+- Added function `setToggleBitValueForRC5AndRC6()`.
+
+# 4.6.0
+- Fixed missing ESP IRAM_ATTR for receiving interrupt.
+- Changed `USE_DEFAULT_FEEDBACK_LED_PIN` from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0.
+- Changed timer for **ATtiny16X4**.
+- Fixed missing initialization with `pinMode()` for feedback LED.
+- Fixed bitmask error in `sendBiphaseData()` when not sending start bit.
+- Improved `decodeSamsung()`.
+- `OpenLASIR` protocol added by [danielweidman](https://github.com/danielweidman).
+- Added `DECODE_MARANTZ` and swapped parameter aMarantzExtension and aNumberOfRepeats of `sendMaranz()` to be consistent with other extensions.
+- Improved biphase decoding.
+- Improved debug output handling.
+- Moved `IRCommandDispatcher` from demo to main library folder.
+- Changed `IRRawDataType` to `IRDecodedRawDataType`.
+
+# 4.5.0 - does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt.
+- Added support for **multiple receiver instances**.
+- irparams_struct `irparams` is now member of IRrecv. Thus removed `rawDataPt`r (pointer to irparams) from `IrReceiver.decodedIRData`.
+- Removed return value for all `decodePulseDistanceWidthData()` decoding functions, which returned a constant true.
+- Removed parameter `aEnableLEDFeedback` in function `IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)` and `IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)`.
+- **LED feedback is always enabled for sending**. It can only be disabled by using the macro `NO_LED_SEND_FEEDBACK_CODE`.
+- Added output for UNKNOWN protocol to `printIRSendUsage()`.
+- Added experimental `sendVelux()`.
+- Added `sendMaranz()`.
+- Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306.
+- Fixed minor bugs in Denon decoder.
+- Minor bug fixes for DEBUG.
+- New handling of `MARK_EXCESS_MICROS` without strange rounding inconsistency.
+- Added experimental threshold decoding.
+
+# 4.4.3
+- Added `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` to make the software aware of send LED connected between VCC and send pin.
+- Fixed backward compatibility bug for `printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros)`.
+- Minor improvements.
+
+# 4.4.2
+- Support for `SAMD51` timer3 if timer 5 is not available (Adafruit ItsyBitsy M4).
+- attachInterrupt() on `SAMD` has a different semantic :-(. See: https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/.
+- Fixed overflow handling.
+- Improved repeat detection for `DistanceWidthProtocol`.
+- Print of IR frame duration in `printIRResultShort()`;
+- `PulseDistanceWidthProtocolConstants` now in PROGMEM, this saves 190 bytes RAM for unit test.
+- Support for PROGMEM PulseDistanceWidthProtocol data.
+- Support duplicated 8 bit address for `sendSamsungLG()`.
+
+# 4.4.1
+- Support for **ESP core 3.x** by akellai.
+- `restartTimer()` now uses variable sMicrosAtLastStopTimer to keep track of uncounted ticks between stopTimer() and restartTimer().
+- **Removed functions** addTicksToInternalTickCounter() and addMicrosToInternalTickCounter(), which were added in 4.1.0.
+- Version 2.2.0 of TinyIR with new `TinyReceiverDecode()` function to be used as **drop in for IrReceiver.decode()**.
+- Support of `RC6A`.
+
+# 4.4.0
+- Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]).
+- Renamed `decodedIRData.initialGap` to `decodedIRData.initialGapTicks`.
+- `sendNEC()` and `sendNEC2()` now **accepts 16 bit command** to better map to **NECext protocol** found in IRDB databases.
+- `ir_DistanceWidthProtocol()` now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k.
+- Improved sensitivity and decoding of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols.
+- Changed `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` to `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT`.
+- Improved examples AllProtocolsOnLCD, UnitTest and SimpleReceiver.
+- New functions `decodePulseDistanceWidthData()` with 6 parameters and `decodePulseDistanceWidthDataStrict()` with 7 parameters.
+
+# 4.3.2
+- Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent.
+- Added sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent.
+- Added ESP32 core 3.x error message.
+
+# 4.3.1
+ - Fixed overflow bug for rawlen > 254.
+ - Removed deprecated sendPulseDistance... functions with parameter aSendStopBit.
+
+# 4.3.0
+- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin).
+ Therefore IrSender.begin(DISABLE_LED_FEEDBACK) will not longer work!
+- Added convenience function isIRReceiverAttachedForTinyReceiver().
+- Added Extended NEC Protocol macro to TinyIR by Buzzerb.
+- Fixed sendSamsung() / sendSamsungLG() bug.
+- Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd().
+- Added rawlen and initialGap to IRData.
+- Added ReceiveAndSendHobToHood example.
+- Changed RECORD_GAP_MICROS default value from 5000 to 8000.
+
+# 4.2.1
+- Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp.
+- TinyReceiver 2.0
+ - 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.
+- Fix changing IR_SEND_PIN dynamically for ESP32.
+- Fix wrong type of tEnableLEDFeedback.
+- Support for ESP32-C3.
+
# 4.2.0
- The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message.
- Added DECODE_ONKYO, to force 16 bit command and data decoding.
- Enable Bang&Olufsen 455 kHz if SEND_PWM_BY_TIMER is defined.
- Fixed bug: TinyReceiver throwing ISR not in IRAM on ESP8266.
- Usage of ATTinyCore pin numbering scheme e.g. PIN_PB2.
+- Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense.
+- First untested support of Uno R4.
+- Extracted version macros to IRVersion.h.
## 4.1.2
- Workaround for ESP32 RTOS delay() timing bug influencing the mark() function.
## 4.1.1
- SAMD51 use timer3 if timer5 not available.
-- Disabled #define LOCAL_DEBUG in IRReceive.hpp, which was accidently enabled at 4.1.0.
+- Disabled #define LOCAL_DEBUG in IRReceive.hpp, which was accidentally enabled at 4.1.0.
## 4.1.0
- Fixed bug in printing durations > 64535 in printIRResultRawFormatted().
@@ -41,7 +150,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Introduced common structure PulseDistanceWidthProtocolConstants.
- Where possible, changed all send and decode functions to use PulseDistanceWidthProtocolConstants.
- Improved MSB/LSB handling
-- New convenience fuctions bitreverse32Bit() and bitreverseOneByte().
+- New convenience functions bitreverse32Bit() and bitreverseOneByte().
- Improved Magiquest protocol.
- Fix for #1028 - Prevent long delay caused by overflow when frame duration < repeat period - Thanks to Stephen Humphries!
- Support for ATtiny816 - Thanks to elockman.
@@ -85,7 +194,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Improved pin mapping for TinyReceiver.
## 3.7.1
-- SendRaw now supports bufferlenght > 255.
+- SendRaw now supports buffer length > 255.
- Improved DistanceProtocol decoder output.
- Fixed ESP32 send bug for 2.x ESP32 cores.
@@ -253,7 +362,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Corrected keywords.txt.
- BoseWave protocol added PR #690.
- Formatting comply to the new stylesheet.
-- Renamed "boarddefs.h" [ISSUE #375](https://github.com/Arduino-IRremote/Arduino-IRremote/issues/375).
+- Renamed "boarddefs.h".
- Renamed `SEND_PIN` to `IR_SEND_PIN`.
- Renamed state macros.
- Enabled `DUTY_CYCLE` for send signal.
@@ -320,7 +429,7 @@ Changes from #268 by adamlhumphreys
- Fixed #110 Mess
- Created Gitter Room
- Added Gitter Badge
-- Standardised Code Base
+- Standardized Code Base
- Clean Debug Output
- Optimized Send Loops
- Modularized Design
@@ -348,4 +457,4 @@ Changes from #268 by adamlhumphreys
- Broke Teensy 3 / 3.1 Support
### Not Working
-- Teensy 3 / 3.1 Support is in Development
+- Teensy 3 / 3.1 Support is in Development
\ No newline at end of file
diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h
index 5aaaaf718..38aa471eb 100644
--- a/examples/AllProtocolsOnLCD/ADCUtils.h
+++ b/examples/AllProtocolsOnLCD/ADCUtils.h
@@ -2,7 +2,6 @@
* 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.
*
@@ -29,6 +28,10 @@
#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
@@ -85,6 +88,7 @@
#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
@@ -92,56 +96,110 @@
#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
-extern float sVCCVoltage;
-extern uint16_t sVCCVoltageMillivolt;
+/*
+ * 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 sLastVoltageCheckMillis;
-extern uint8_t sVoltageTooLowCounter;
-
-uint16_t readADCChannel(uint8_t aChannelNumber);
-uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
-uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
-uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aChannelNumber, uint8_t aReference);
-uint16_t readADCChannelWithOversample(uint8_t aChannelNumber, uint8_t aOversampleExponent);
-void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference);
-uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
-uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
-uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
-uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
-uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
-uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference,
- uint8_t aMaxRetries);
-
-uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference);
+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);
-uint16_t getVCCVoltageMillivoltSimple(void);
void readVCCVoltageMillivoltSimple(void);
-float getVCCVoltage(void);
void readVCCVoltage(void);
uint16_t getVCCVoltageMillivolt(void);
void readVCCVoltageMillivolt(void);
@@ -152,12 +210,32 @@ 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 getTemperatureSimple(void);
-float getTemperature(void);
-
-bool isVCCTooLowMultipleTimes();
-void resetVCCTooLowMultipleTimes();
-bool isVoltageTooLow();
+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
diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp
index 079d177da..ef9aad8da 100644
--- a/examples/AllProtocolsOnLCD/ADCUtils.hpp
+++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp
@@ -3,8 +3,7 @@
*
* ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h.
*
- * Copyright (C) 2016-2022 Armin Joachimsmeyer
- * Email: armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2016-2023 Armin Joachimsmeyer
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
@@ -26,19 +25,25 @@
#define _ADC_UTILS_HPP
#include "ADCUtils.h"
-#if defined(ADC_UTILS_ARE_AVAILABLE)
+#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected
+#define ADC_UTILS_ARE_INCLUDED
-#if !defined(STR_HELPER)
+// 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 value > real AREF voltage, measured values are > real values
*/
#if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT)
-#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
+#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100 // Change to value measured at the AREF pin.
#endif
// Union to speed up the combination of low and high bytes to a word
@@ -54,22 +59,37 @@ union WordUnionForADCUtils {
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;
+uint16_t sVCCVoltageMillivolt; // Set by readVCCVoltageMillivoltSimple(), readVCCVoltageMillivolt()
// for isVCCTooLowMultipleTimes()
-long sLastVoltageCheckMillis;
-uint8_t sVoltageTooLowCounter = 0;
+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(uint8_t aChannelNumber) {
+uint16_t readADCChannel() {
WordUnionForADCUtils tUValue;
- ADMUX = aChannelNumber | (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
@@ -85,12 +105,32 @@ uint16_t readADCChannel(uint8_t aChannelNumber) {
// 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 aChannelNumber, uint8_t aReference) {
+uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
WordUnionForADCUtils tUValue;
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+ 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
@@ -105,22 +145,38 @@ uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference)
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 aChannelNumber, uint8_t aReference) {
- checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference);
- return readADCChannelWithReference(aChannelNumber, aReference);
+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 aChannelNumber, uint8_t aReference) {
- uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference);
- uint16_t tResult = readADCChannelWithReference(aChannelNumber, aReference);
+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;
}
@@ -128,15 +184,28 @@ uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t a
/*
* To prepare reference and ADMUX for next measurement
*/
-void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference) {
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+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 aChannelNumber, uint8_t aReference) {
+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)
@@ -146,18 +215,21 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8
* 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 = aChannelNumber | tNewReference;
+ 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 & 0x0F) != aChannelNumber) {
- if (aChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
+ 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
*/
@@ -176,16 +248,16 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8
* 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 aChannelNumber, uint8_t aOversampleExponent) {
- return readADCChannelWithReferenceOversample(aChannelNumber, DEFAULT, aOversampleExponent);
+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 aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
+uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+ 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
@@ -212,9 +284,9 @@ uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t a
/*
* Use ADC_PRESCALE32 which gives 26 us conversion time and good linearity for 16 MHz Arduino
*/
-uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
+uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+ 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
@@ -239,11 +311,12 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8
/*
* Returns sum of all sample values
- * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h.
+ * 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 readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
+uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t tSumValue = 0;
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+ 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
@@ -265,14 +338,73 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t
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 of aNumberOfSamples measurements.
+ * @return the maximum value of aNumberOfSamples samples.
*/
-uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) {
+uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) {
uint16_t tADCValue = 0;
uint16_t tMaximum = 0;
- ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
+ 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
@@ -298,33 +430,41 @@ uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReferen
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
+ * @return the maximum value during aMicrosecondsToAquire measurement.
*/
-uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
+uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
uint16_t tNumberOfSamples = aMicrosecondsToAquire / 26;
- return readADCChannelWithReferenceMax(aChannelNumber, aReference, tNumberOfSamples);
+ return readADCChannelWithReferenceMax(aADCChannelNumber, aReference, tNumberOfSamples);
}
/*
* aMaxRetries = 255 -> try forever
* @return (tMax + tMin) / 2
*/
-uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference,
- uint8_t aMaxRetries) {
- int tValues[4];
+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;
- tValues[0] = readADCChannel(aChannelNumber);
+ /*
+ * Initialize first 4 values before checking
+ */
+ tValues[0] = readADCChannelWithReference(aADCChannelNumber, aReference);
for (int i = 1; i < 4; ++i) {
- delay(aDelay); // Only 3 delays!
- tValues[i] = readADCChannel(aChannelNumber);
+ if (aDelay != 0) {
+ delay(aDelay); // Minimum is only 3 delays!
+ }
+ tValues[i] = readADCChannelWithReference(aADCChannelNumber, aReference);
}
do {
- // find min and max
- tMin = 1024;
+ /*
+ * Get min and max of the last 4 values
+ */
+ tMin = READING_FOR_AREF;
tMax = 0;
- for (int i = 0; i < 4; ++i) {
+ for (uint_fast8_t i = 0; i < 4; ++i) {
if (tValues[i] < tMin) {
tMin = tValues[i];
}
@@ -338,22 +478,44 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe
if ((tMax - tMin) <= aAllowedDifference) {
break;
} else {
+ /*
+ * Get next value
+ */
// Serial.print("Difference=");
// Serial.println(tMax - tMin);
-
- // move values
+ // Move values to front
for (int i = 0; i < 3; ++i) {
tValues[i] = tValues[i + 1];
}
- // and wait
- delay(aDelay);
- tValues[3] = readADCChannel(aChannelNumber);
+ // 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;
}
@@ -361,11 +523,15 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe
* !!! 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 = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- return ((1023 * 1.1 * 4) / tVCC);
+ float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
+ return ((READING_FOR_AREF * 1.1 * 4) / tVCC);
}
/*
@@ -375,20 +541,20 @@ float getVCCVoltageSimple(void) {
*/
uint16_t getVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
- uint16_t tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
+ 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() * 1023 / 1100
+ * Similar to getVCCVoltageMillivolt() * 1024 / 1100
*/
uint16_t getVCCVoltageReadingFor1_1VoltReference(void) {
- uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT); // 225 for 1.1 V at 5 V VCC
+ 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 ((1023L * 1023L) / tVCC);
+ return (((uint32_t)READING_FOR_AREF * READING_FOR_AREF) / tVCC);
}
/*
@@ -402,15 +568,22 @@ float getVCCVoltage(void) {
* 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 ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
+ 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();
@@ -432,8 +605,8 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
*/
void readVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
- float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- sVCCVoltage = (1023 * 1.1 * 4) / tVCC;
+ float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
+ sVCCVoltage = (READING_FOR_AREF * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}
/*
@@ -443,8 +616,8 @@ void readVCCVoltageSimple(void) {
*/
void readVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
- uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
+ uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
+ sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}
/*
@@ -465,7 +638,7 @@ void readVCCVoltageMillivolt(void) {
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
- sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
+ sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
}
/*
@@ -474,7 +647,7 @@ void readVCCVoltageMillivolt(void) {
*/
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
- return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / 1023;
+ return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
@@ -483,42 +656,54 @@ uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelF
*/
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
- return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / 1023;
+ 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) / 1023;
+ return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
- * 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.
+ * 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.
*/
-#if !defined(VCC_STOP_THRESHOLD_MILLIVOLT)
-#define VCC_STOP_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
-#endif
-#if !defined(VCC_EMERGENCY_STOP_MILLIVOLT)
-#define VCC_EMERGENCY_STOP_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
-#endif
-#if !defined(VCC_CHECK_PERIOD_MILLIS)
-#define VCC_CHECK_PERIOD_MILLIS 10000 // Period of VCC checks
-#endif
-#if !defined(VCC_CHECKS_TOO_LOW_BEFORE_STOP)
-#define VCC_CHECKS_TOO_LOW_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_STOP_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_STOP_MILLIVOLT
-#endif
+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;
+}
/*
- * @ return true only once, when VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times voltage too low -> shutdown
+ * 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 isVCCTooLowMultipleTimes() {
+bool isVCCUndervoltageMultipleTimes() {
/*
- * Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds
+ * Check VCC every VCC_CHECK_PERIOD_MILLIS - default is 10 seconds
*/
-
- if (millis() - sLastVoltageCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
- sLastVoltageCheckMillis = millis();
+ if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
+ sLastVCCCheckMillis = millis();
# if defined(INFO)
readAndPrintVCCVoltageMillivolt(&Serial);
@@ -526,33 +711,37 @@ bool isVCCTooLowMultipleTimes() {
readVCCVoltageMillivolt();
# endif
- if (sVoltageTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
- /*
- * Do not check again if shutdown has happened
- */
- if (sVCCVoltageMillivolt > VCC_STOP_THRESHOLD_MILLIVOLT) {
- sVoltageTooLowCounter = 0; // reset counter
+ /*
+ * 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_CHECKS_TOO_LOW_BEFORE_STOP (6) times and then shut down.
+ * Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then signal shut down.
*/
- if (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT) {
+ if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
// emergency shutdown
- sVoltageTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP;
-# if defined(INFO)
- Serial.println(F("Voltage < " STR(VCC_EMERGENCY_STOP_MILLIVOLT) " mV detected -> 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 {
- sVoltageTooLowCounter++;
-# if defined(INFO)
- Serial.print(F("Voltage < " STR(VCC_STOP_THRESHOLD_MILLIVOLT) " mV detected: "));
- Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVoltageTooLowCounter);
- Serial.println(F(" tries left"));
+ 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 (sVoltageTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
+ if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
/*
- * 6 times voltage too low -> shutdown
+ * 6 times voltage too low -> return signal for shutdown etc.
*/
return true;
}
@@ -562,47 +751,134 @@ bool isVCCTooLowMultipleTimes() {
return false;
}
-void resetVCCTooLowMultipleTimes(){
- sVoltageTooLowCounter = 0;
+/*
+ * 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);
}
-bool isVoltageTooLow(){
- return (sVoltageTooLowCounter >= VCC_CHECKS_TOO_LOW_BEFORE_STOP);
+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 (call getTemperatureSimple()) in your program.
+ * Use it ONLY if you only use INTERNAL reference (e.g. only call getTemperatureSimple()) in your program.
*/
-float getTemperatureSimple(void) {
+float getCPUTemperatureSimple(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
return 0.0;
#else
-// use internal 1.1 volt as reference
- float tTemp = (readADCChannelWithReferenceMultiSamples(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2) - 317);
- return (tTemp * (4 / 1.22));
+ // 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 reference and channel switching by introducing the appropriate delays.
+ * 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);
- // assume the signal has noise, but never verified :-(
- float tTemp = (readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 1) - 317);
- return (tTemp / 1.22);
+ return getCPUTemperatureSimple();
#endif
}
-#elif defined(ARDUINO_ARCH_APOLLO3) // defined(ADC_UTILS_ARE_AVAILABLE)
- void ADCUtilsDummyToAvoidBFDAssertions(){
- ;
- }
+#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
diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
index bc514a194..62a8a9282 100644
--- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
+++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2023 Armin Joachimsmeyer
+ * 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
@@ -33,15 +33,22 @@
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
-#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Here we most likely have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 750
+# endif
+
+# if RAMSIZE <= 0x800
+#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds
+# else
+#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 400 // The decoder accepts mark or space durations up to 400 * 50 (MICROS_PER_TICK) = 20 milliseconds
# endif
#endif
@@ -54,12 +61,14 @@
#endif
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 120 bytes program memory.
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols.
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
//#define DECODE_NEC // Includes Apple and Onkyo
@@ -73,19 +82,30 @@
* because of the long lasting serial communication.
*/
//#define USE_NO_LCD
-//#define USE_SERIAL_LCD
-// Definitions for the 1602 LCD
-#define LCD_COLUMNS 16
-#define LCD_ROWS 2
-
-#if defined(USE_SERIAL_LCD)
-#include "LiquidCrystal_I2C.h" // Use an up to date library version, which has the init method
+#if !defined(USE_NO_LCD)
+#define USE_LCD
+#define USE_PARALLEL_2004_LCD // Is default
+//#define USE_SERIAL_1602_LCD
+#include "LCDPrintUtils.hpp" // sets USE_PARALLEL_LCD or USE_SERIAL_LCD
+# if defined(USE_SERIAL_LCD)
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)
-#define USE_PARALLEL_LCD
-#include "LiquidCrystal.h"
+# else
//LiquidCrystal myLCD(4, 5, 6, 7, 8, 9);
LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
+# endif
+# if defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
+// For cyclically display of VCC and isVCCUSBPowered()
+#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4250
+#include "ADCUtils.hpp"
+#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
+#define LCD_VOLTAGE_START_INDEX 11
+uint32_t volatile sMillisOfLastVoltagePrint = 0;
+bool ProtocolStringOverwritesVoltage = false;
+# endif
+#define LCD_IR_COMMAND_START_INDEX 9
+
+void printsVCCVoltageMillivoltOnLCD();
+void printIRResultOnLCD();
#endif
#if defined(USE_PARALLEL_LCD)
@@ -95,31 +115,13 @@ LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
#else
#define DEBUG_BUTTON_PIN 6
#endif
-#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug
+#if defined(__AVR_ATmega328P__)
+#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug with pin 11
+#endif
#define MILLIS_BETWEEN_ATTENTION_BEEP 60000 // 60 sec
uint32_t sMillisOfLastReceivedIRFrame = 0;
-#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
-#define USE_LCD
-# if defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
-// For cyclically display of VCC
-#include "ADCUtils.hpp"
-#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
-#define LCD_VOLTAGE_START_INDEX 11
-uint32_t volatile sMillisOfLastVoltagePrint = 0;
-bool ProtocolStringOverwritesVoltage = false;
-# endif
-#define LCD_IR_COMMAND_START_INDEX 9
-
-#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
-
-void printIRResultOnLCD();
-size_t printByteHexOnLCD(uint16_t aHexByteValue);
-void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint);
-
-uint16_t sVCCMillivolt;
-
void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
@@ -130,7 +132,9 @@ void setup() {
#endif
Serial.begin(115200);
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
+
+#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
@@ -158,31 +162,37 @@ void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
Serial.println();
- Serial.print(F("If you connect debug pin "));
-# if defined(APPLICATION_PIN_STRING)
- Serial.print(APPLICATION_PIN_STRING);
-# else
- Serial.print(DEBUG_BUTTON_PIN);
-# endif
- Serial.print(F(" to ground or to pin "));
- Serial.print(AUXILIARY_DEBUG_BUTTON_PIN);
- Serial.println(F(", raw data is always printed"));
+ if (digitalRead(DEBUG_BUTTON_PIN) != LOW) {
+ Serial.print(F("If you connect debug pin "));
+ Serial.print(DEBUG_BUTTON_PIN);
+ Serial.print(F(" to ground"));
+# if defined(AUXILIARY_DEBUG_BUTTON_PIN)
+ Serial.print(F(" or to pin "));
+ Serial.print(AUXILIARY_DEBUG_BUTTON_PIN);
+#endif
+ Serial.println(F(", raw data is always printed"));
+ }
- // infos for receive
+ // Info for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
-#if defined(USE_LCD) && defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
- getVCCVoltageMillivoltSimple(); // to initialize ADC mux and reference
+#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
+ readVCCVoltageMillivolt();
#endif
#if defined(USE_SERIAL_LCD)
myLCD.init();
myLCD.clear();
- myLCD.backlight();
+ myLCD.backlight(); // Switch backlight LED on
#endif
#if defined(USE_PARALLEL_LCD)
myLCD.begin(LCD_COLUMNS, LCD_ROWS); // This also clears display
@@ -196,7 +206,7 @@ void setup() {
#endif
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
- sVCCMillivolt = getVCCVoltageMillivoltSimple();
+ readVCCVoltageMillivolt();
#endif
}
@@ -226,17 +236,18 @@ void loop() {
} else {
// play tone
auto tStartMillis = millis();
- IrReceiver.stop();
+// IrReceiver.stopTimer(); // Not really required for Uno, but we then should use restartTimer(aMicrosecondsToAddToGapCounter)
tone(TONE_PIN, 2200);
if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW)
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
- && sVCCMillivolt > 4222
+ || isVCCUSBPowered()
#endif
- ) {
- // Print more info, but only if we are connected to USB, i.e. VCC is > 4222 mV, because this may take to long to detect some fast repeats
+ ) {
+ // Print more info, but only if we are connected to USB, i.e. VCC is > 4300 mV, because this may take to long to detect some fast repeats
IrReceiver.printIRSendUsage(&Serial);
- IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-)
+// IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-)
+ IrReceiver.printIRResultRawFormatted(&Serial); // print us, this is better to compare :-)
}
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
@@ -244,9 +255,7 @@ void loop() {
while ((millis() - tStartMillis) < 5)
;
noTone(TONE_PIN);
-
- // Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
- IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
+ IrReceiver.restartTimer(5000); // Restart IR timer.
#if defined(USE_LCD)
printIRResultOnLCD();
@@ -261,15 +270,22 @@ void loop() {
} // if (IrReceiver.decode())
/*
- * Check for attention every 10 minute, after the current measurement was finished
+ * Check if generating attention beep every minute, after the current measurement was finished
*/
- if (millis() - sMillisOfLastReceivedIRFrame >= MILLIS_BETWEEN_ATTENTION_BEEP) {
+ if ((millis() - sMillisOfLastReceivedIRFrame) >= MILLIS_BETWEEN_ATTENTION_BEEP
+#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
+ && !isVCCUSBPowered()
+#endif
+ ) {
sMillisOfLastReceivedIRFrame = millis();
- IrReceiver.stop();
+#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
+ printsVCCVoltageMillivoltOnLCD();
+#endif
+// IrReceiver.stopTimer(); // Not really required for Uno, but we then should use restartTimer(aMicrosecondsToAddToGapCounter)
tone(TONE_PIN, 2200);
delay(50);
noTone(TONE_PIN);
- IrReceiver.startWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
+ IrReceiver.restartTimer(50000);
}
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
@@ -279,18 +295,25 @@ void loop() {
* Periodically print VCC
*/
sMillisOfLastVoltagePrint = millis();
- sVCCMillivolt = getVCCVoltageMillivoltSimple();
- char tVoltageString[5];
- dtostrf(sVCCMillivolt / 1000.0, 4, 2, tVoltageString);
- myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
- myLCD.print(' ');
- myLCD.print(tVoltageString);
- myLCD.print('V');
+ readVCCVoltageMillivolt();
+ printsVCCVoltageMillivoltOnLCD();
}
#endif
}
+#if defined(USE_LCD)
+void printsVCCVoltageMillivoltOnLCD() {
+# if defined(ADC_UTILS_ARE_AVAILABLE)
+ char tVoltageString[5];
+ dtostrf(sVCCVoltageMillivolt / 1000.0, 4, 2, tVoltageString);
+ myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
+ myLCD.print(' ');
+ myLCD.print(tVoltageString);
+ myLCD.print('V');
+# endif
+}
+
/*
* LCD output for 1602 LCDs
* 40 - 55 Milliseconds per initial output
@@ -300,7 +323,6 @@ void loop() {
*
*/
void printIRResultOnLCD() {
-#if defined(USE_LCD)
static uint16_t sLastProtocolIndex = 4711;
static uint16_t sLastProtocolAddress = 4711;
static uint16_t sLastCommand = 0;
@@ -321,42 +343,45 @@ void printIRResultOnLCD() {
// we overwrite the voltage -> clear rest of line and inhibit new printing of voltage
ProtocolStringOverwritesVoltage = true;
if (tProtocolStringLength < LCD_COLUMNS) {
- printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength);
+ LCDPrintSpaces(&myLCD, LCD_COLUMNS - tProtocolStringLength);
}
} else {
// Trigger printing of VCC in main loop
sMillisOfLastVoltagePrint = 0;
ProtocolStringOverwritesVoltage = false;
- printSpacesOnLCD(LCD_VOLTAGE_START_INDEX - tProtocolStringLength);
+ LCDPrintSpaces(&myLCD, LCD_VOLTAGE_START_INDEX - tProtocolStringLength);
}
# else
- printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength);
+ LCDPrintSpaces(&myLCD, LCD_COLUMNS - tProtocolStringLength);
# endif
}
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
/*
- * Print number of bits received and microseconds of signal
+ * Print number of bits received and hash code
+ * "123 bit 5E7E4778"
*/
myLCD.setCursor(0, 1);
- uint8_t tNumberOfBits = (IrReceiver.decodedIRData.rawDataPtr->rawlen + 1) / 2;
+ uint8_t tNumberOfBits = (IrReceiver.irparams.rawlen + 1) / 2;
+ uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits); // tPrintedStringLength = 1 to 3
+ myLCD.print(F(" bit ")); // 5 characters
+
if (tNumberOfBits < 10) {
- myLCD.print(' '); // padding space
+ myLCD.print(F("0x"));
+ tPrintedStringLength += 2;
}
- myLCD.print(tNumberOfBits);
- myLCD.print(F(" bit "));
- uint_fast8_t tDurationStringLength = myLCD.print(IrReceiver.getTotalDurationOfRawData());
- myLCD.print(F(" \xE4s")); // \xE4 is micro symbol
- printSpacesOnLCD(7 - tDurationStringLength);
+ tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX); // maximum is += 8;
+ LCDPrintSpaces(&myLCD, (LCD_COLUMNS - 5) - tPrintedStringLength);
sLastProtocolAddress = 4711;
- sLastCommand = 44711;
+ sLastCommand = 4711;
} else {
/*
- * Print only if address has changed
+ * Protocol is know here
+ * Print address only if it has changed or is PULSE_DISTANCE or PULSE_WIDTH
*/
- if (sLastProtocolAddress != IrReceiver.decodedIRData.address) {
- sLastProtocolAddress = IrReceiver.decodedIRData.address;
+ if (sLastProtocolAddress != IrReceiver.decodedIRData.address || IrReceiver.decodedIRData.protocol == PULSE_DISTANCE
+ || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
myLCD.setCursor(0, 1);
/*
@@ -364,16 +389,24 @@ void printIRResultOnLCD() {
*/
# if defined(DECODE_DISTANCE_WIDTH)
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
+ sLastProtocolAddress = 4711; // To enforce next print of address
myLCD.print(F("[0]=0x"));
uint_fast8_t tAddressStringLength = myLCD.print(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
- printSpacesOnLCD(LCD_COLUMNS - tAddressStringLength);
- sLastCommand = 0; // to trigger restoration of "C=" string
- return; // no command here
+ LCDPrintSpaces(&myLCD, LCD_COLUMNS - tAddressStringLength);
+ sLastCommand = 0; // to trigger restoration of "C=" string, if another protocol is received
+ /*
+ * No command here!
+ */
+ return;
+
} else {
# endif
+ sLastProtocolAddress = IrReceiver.decodedIRData.address;
+// Serial.print(F("Print address 0x"));
+// Serial.println(IrReceiver.decodedIRData.address, HEX);
myLCD.print(F("A="));
- uint_fast8_t tAddressStringLength = printByteHexOnLCD(IrReceiver.decodedIRData.address);
- printSpacesOnLCD((LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength);
+ uint_fast8_t tAddressStringLength = LCDPrintHex(&myLCD, IrReceiver.decodedIRData.address);
+ LCDPrintSpaces(&myLCD, (LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength);
# if defined(DECODE_DISTANCE_WIDTH)
}
# endif
@@ -403,8 +436,12 @@ void printIRResultOnLCD() {
/*
* Command data
*/
+// Serial.print(F("Print command 0x"));
+// Serial.print(tCommand, HEX);
+// Serial.print(F(" at "));
+// Serial.println(sLastCommandPrintPosition);
myLCD.setCursor(sLastCommandPrintPosition, 1);
- printByteHexOnLCD(tCommand);
+ LCDPrintHex(&myLCD, tCommand);
/*
* Show or clear repetition flag
@@ -416,23 +453,5 @@ void printIRResultOnLCD() {
myLCD.print(' ');
}
} // IrReceiver.decodedIRData.protocol == UNKNOWN
-#endif // defined(USE_LCD)
-}
-
-#if defined(USE_LCD)
-size_t printByteHexOnLCD(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;
-}
-
-void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint) {
- for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
- myLCD.print(' ');
- }
}
-#endif
+#endif // defined(USE_LCD)
diff --git a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp
new file mode 100644
index 000000000..84b78300b
--- /dev/null
+++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp
@@ -0,0 +1,397 @@
+/*
+ * LCDPrintUtils.hpp
+ *
+ * Contains LCD related variables and functions
+ * Sets symbols USE_SERIAL_LCD or USE_PARALLEL_LCD and LCD_COLUMNS and LCD_ROWS
+ *
+ * Copyright (C) 2024-2025 Armin Joachimsmeyer
+ *
+ * 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 .
+ */
+
+#ifndef _LCD_PRINT_UTILS_HPP
+#define _LCD_PRINT_UTILS_HPP
+
+//#define LOCAL_DEBUG // This enables debug output only for this file - only for development
+
+//#define USE_PARALLEL_2004_LCD // Is default
+//#define USE_PARALLEL_1602_LCD
+//#define USE_SERIAL_2004_LCD
+//#define USE_SERIAL_1602_LCD
+
+#if !defined(USE_PARALLEL_2004_LCD) && !defined(USE_PARALLEL_1602_LCD) && !defined(USE_SERIAL_2004_LCD) && !defined(USE_SERIAL_1602_LCD)
+#warning "No LCD type like USE_SERIAL_2004_LCD specified, therefore using USE_PARALLEL_2004_LCD as default"
+#define USE_PARALLEL_2004_LCD // Use parallel 2004 LCD as default
+#endif
+
+#if defined(USE_PARALLEL_2004_LCD) || defined(USE_PARALLEL_1602_LCD)
+#define USE_PARALLEL_LCD
+#include "LiquidCrystal.h"
+#else
+#define USE_SERIAL_LCD
+#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster
+#endif
+
+#if defined(USE_PARALLEL_1602_LCD) || defined(USE_SERIAL_1602_LCD)
+#define LCD_COLUMNS 16
+#define LCD_ROWS 2
+#else
+#define LCD_COLUMNS 20
+#define LCD_ROWS 4
+#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
+
+#define DEGREE_SIGN_STRING "\xDF"
+
+extern char sStringBuffer[]; // For rendering a LCD row with snprintf_P()
+
+#if defined(USE_PARALLEL_LCD)
+void LCDResetCursor(LiquidCrystal *aLCD);
+void LCDPrintSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint);
+void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber); // Cursor is a start of line
+size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue);
+void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal *aLCD, uint16_t aValueInMilliUnits);
+void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint,
+ bool aNoLeadingSpaceForPositiveValues = false);
+void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD);
+void LCDShowSpecialCharacters(LiquidCrystal *aLCD);
+void LCDShowCustomCharacters(LiquidCrystal *aLCD);
+#else
+void LCDResetCursor(LiquidCrystal_I2C *aLCD);
+void LCDPrintSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint);
+void LCDClearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber);
+size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue);
+void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts);
+void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint,
+ bool aNoLeadingSpaceForPositiveValues = false);
+void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD);
+void LCDShowSpecialCharacters(LiquidCrystal_I2C *aLCD);
+void LCDShowCustomCharacters(LiquidCrystal_I2C *aLCD);
+#endif
+uint8_t getNumberOfDecimalsFor16BitValues(uint16_t a16BitValue);
+
+/*
+ * Code starts here
+ */
+
+#if defined(USE_PARALLEL_LCD)
+void LCDResetCursor(LiquidCrystal *aLCD)
+#else
+void LCDResetCursor(LiquidCrystal_I2C *aLCD)
+#endif
+ {
+ aLCD->setCursor(0, 0);
+}
+
+#if defined(USE_PARALLEL_LCD)
+void LCDPrintSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint)
+#else
+void LCDPrintSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint)
+#endif
+ {
+ for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
+ aLCD->print(' ');
+ }
+}
+
+#if defined(USE_PARALLEL_LCD)
+void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber)
+#else
+void LCDClearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber)
+#endif
+ {
+ aLCD->setCursor(0, aLineNumber);
+ LCDPrintSpaces(aLCD, LCD_COLUMNS);
+ aLCD->setCursor(0, aLineNumber);
+}
+
+#if defined(USE_PARALLEL_LCD)
+size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue)
+#else
+size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue)
+#endif
+ {
+ aLCD->print(F("0x"));
+ size_t tPrintSize = 2;
+ if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) {
+ aLCD->print('0'); // leading 0
+ tPrintSize++;
+ }
+ return aLCD->print(aHexByteValue, HEX) + tPrintSize;
+}
+
+/*
+ * Use 2 decimals, if value is >= 10
+ */
+#if defined(USE_PARALLEL_LCD)
+void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal *aLCD, uint16_t aValueInMilliUnits)
+#else
+void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal_I2C *aLCD, uint16_t aValueInMilliUnits)
+#endif
+ {
+ if (aValueInMilliUnits < 10000) {
+ aLCD->print(((float) (aValueInMilliUnits)) / 1000, 3);
+ } else {
+ aLCD->print(((float) (aValueInMilliUnits)) / 1000, 2);
+ }
+}
+
+/*
+ * @return 1 for values from 0 to 9, 2 for 10 to 99 up to 5 for >= 10,000
+ */
+uint8_t getNumberOfDecimalsFor16BitValues(uint16_t a16BitValue) {
+ uint16_t tCompareValue = 1;
+ /*
+ * Check for 10, 100, 1000
+ */
+ for (uint_fast8_t tNumberOfDecimals = 0; tNumberOfDecimals < 5; ++tNumberOfDecimals) {
+ if (a16BitValue < tCompareValue) {
+ return tNumberOfDecimals;
+ }
+ tCompareValue *= 10;
+ }
+ // here we have values >= 10,000
+ return 5;
+}
+
+/*
+ * @return 1 for values from 0 to 9, 2 for 10 to 99 up to 10 for >= 1,000,000,000
+ * Requires 26 bytes more program space than getNumberOfDecimalsFor16BitValues()
+ */
+uint8_t getNumberOfDecimalsFor32BitValues(uint32_t a32BitValue) {
+ uint_fast8_t tNumberOfDecimals = 1;
+ uint32_t tCompareValue = 10;
+ /*
+ * Check for 10, 100, 1000 up to 100,000,000
+ */
+ for (; tNumberOfDecimals < 10; ++tNumberOfDecimals) {
+ if (a32BitValue < tCompareValue) {
+ return tNumberOfDecimals;
+ }
+ tCompareValue *= 10;
+ }
+ // here we have values >= 1,000,000,000
+ return 10;
+}
+/*
+ * !!! We internally use uint16_t, thus for bigger values (> 65,536 or < -65,536) we have an overflow.
+ * @param aNoLeadingSpaceForPositiveValues - Normally each positive value has a leading space as placeholder for the minus sign.
+ * If we know, that values are always positive, this space can be omitted by aNoLeadingSpaceForPositiveValues == true.
+ * @param aNumberOfCharactersToPrint - The characters to be used for the most negative value to show. !!! MUST BE < 8, This is NOT checked!!!
+ * I.e. 4 => max negative value is "-999" max positive value is " 999".
+ * Values below 10 and -10 are displayed as floats with decimal point " 9.9" and "-9.9".
+ * Values below 1 and -1 are displayed as floats without 0 before decimal point " .9" and "-.9".
+ * If positive, there is a leading space, which improves readability if directly concatenated to another value.
+ * e.g. "71V1.189A" is not readable, "71V 1.18A" is as well as "71V-1.18A".
+ *
+ * Saves programming space if used more than 1 times for printing floats if used instead of myLCD.print(JKComputedData.BatteryVoltageFloat, 2);
+ */
+#if defined(USE_PARALLEL_LCD)
+void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint,
+ bool aNoLeadingSpaceForPositiveValues)
+#else
+void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint,
+ bool aNoLeadingSpaceForPositiveValues)
+#endif
+ {
+
+ uint8_t tNumberOfDecimals = getNumberOfDecimalsFor16BitValues(abs(aFloatValue)); // remove sign for length computation
+ int8_t tNumberOfDecimalPlaces = (aNumberOfCharactersToPrint - 2) - tNumberOfDecimals;
+ if (aNoLeadingSpaceForPositiveValues && aFloatValue >= 0) {
+ tNumberOfDecimalPlaces++; // Use this increased value internally, since we do not eventually print the '-'
+ }
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("NumberOfDecimalPlaces("));
+ Serial.print(tNumberOfDecimals);
+ Serial.print(F(", "));
+ Serial.print(aNumberOfCharactersToPrint);
+ Serial.print(F(")="));
+ Serial.print(tNumberOfDecimalPlaces);
+ Serial.print(F(" NumberOfDecimals="));
+ Serial.println(tNumberOfDecimals);
+#endif
+ if (tNumberOfDecimalPlaces < 0) {
+ tNumberOfDecimalPlaces = 0;
+ }
+
+ char tStringBuffer[9]; // For aNumberOfCharactersToPrint up to 8
+ uint8_t tStartIndex = 0;
+ if (tNumberOfDecimals == 0 && tNumberOfDecimalPlaces > 0) {
+ if (aFloatValue >= 0) {
+ if (!aNoLeadingSpaceForPositiveValues) {
+ aLCD->print(' ');
+ }
+ tStartIndex = 1;
+ } else {
+ aLCD->print('-');
+ tStartIndex = 2;
+ }
+ }
+#if defined(__AVR__)
+ dtostrf(aFloatValue, aNumberOfCharactersToPrint, tNumberOfDecimalPlaces, tStringBuffer);
+#else
+ snprintf(sStringBuffer, sizeof(tStringBuffer), "%f", aFloatValue);
+#endif
+ aLCD->print(&tStringBuffer[tStartIndex]);
+}
+/**
+ * Unit test for LCDPrintFloatValueRightAligned()
+ * @param aSerial
+ * @param aLCD
+ */
+#if defined(USE_PARALLEL_LCD)
+void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD)
+#else
+void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal_I2C *aLCD)
+#endif
+ {
+ aSerial->println(F("LCDTestPrintFloatValueRightAligned: 1."));
+
+ aLCD->clear();
+ float tTestValue = 123.45;
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4); // no leading space here
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3); // no leading space here
+ // Result=" 123.4 123 123123"
+
+ aLCD->setCursor(0, 1);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 6);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 5);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 4);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 3); // requires also 5 character
+ // Result="-123.4 -123-123-123"
+
+ aLCD->setCursor(0, 2);
+ tTestValue = -1.234;
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2);
+ // Result="-1.234-1.23-1.2 -1-1"
+
+ aLCD->setCursor(0, 3);
+ tTestValue = -0.1234;
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2);
+ // Result="-.1234-.123-.12-.1-0"
+
+ delay(4000);
+ aSerial->println(F("LCDTestPrintFloatValueRightAligned: 2."));
+
+ aLCD->clear();
+ tTestValue = 123.45;
+ // no leading space here
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true);
+ // Result="123.45123.4 123123"
+
+ aLCD->setCursor(0, 1);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 6, true);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 5, true);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 4, true);
+ LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 3, true);
+ // Result="-123.4 -123-123-123"
+
+ tTestValue = 1.2344; // .12345 leads to rounding up for .1235
+ aLCD->setCursor(0, 2);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2, true);
+ // Result="1.23441.2341.231.2 1"
+
+ tTestValue = 0.12344; // .12345 leads to rounding up for .1235
+ aLCD->setCursor(0, 3);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true);
+ LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2, true);
+ // Result=".12344.1234.123.12.1"
+
+ delay(4000);
+ aSerial->println(F("LCDTestPrintFloatValueRightAligned: End"));
+}
+
+/*
+ * On my 2004 LCD the custom characters are available under 0 to 7 and mirrored to 8 to 15
+ * The characters 0x80 to 0x8F are blanks
+ */
+#if defined(USE_PARALLEL_LCD)
+void LCDShowSpecialCharacters(LiquidCrystal *aLCD)
+#else
+void LCDShowSpecialCharacters(LiquidCrystal_I2C *aLCD)
+#endif
+ {
+ aLCD->setCursor(0, 0);
+ // 0 to 7 are mirrored to 8 to 15 as described in datasheet
+ for (uint_fast8_t i = 0; i < 0x8; ++i) {
+ aLCD->write(i);
+ }
+ // Print some interesting characters
+ aLCD->write(0xA1);
+ aLCD->write(0xA5);
+ aLCD->write(0xB0);
+ aLCD->write(0xDB);
+ aLCD->write(0xDF);
+
+ aLCD->setCursor(0, 1);
+ // The characters 0x10 to 0x1F seem to be all blanks => ROM Code: A00
+ for (uint_fast8_t i = 0x10; i < 0x20; ++i) {
+ aLCD->write(i);
+ }
+ aLCD->setCursor(0, 2);
+ // The characters 0x80 to 0x8F seem to be all blanks => ROM Code: A00
+ for (uint_fast8_t i = 0x80; i < 0x90; ++i) {
+ aLCD->write(i);
+ }
+ aLCD->setCursor(0, 3);
+ // The characters 0x90 to 0x9F seem to be all blanks => ROM Code: A00
+ for (uint_fast8_t i = 0x90; i < 0xA0; ++i) {
+ aLCD->write(i);
+ }
+ delay(2000);
+}
+
+#if defined(USE_PARALLEL_LCD)
+void LCDShowCustomCharacters(LiquidCrystal *aLCD)
+#else
+void LCDShowCustomCharacters(LiquidCrystal_I2C *aLCD)
+#endif
+ {
+ aLCD->setCursor(0, 0);
+ for (uint_fast8_t i = 0; i < 0x08; ++i) {
+ aLCD->write(i);
+ }
+}
+
+#if defined(LOCAL_DEBUG)
+#undef LOCAL_DEBUG
+#endif
+#endif // _LCD_PRINT_UTILS_HPP
diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
index 5dcef0838..240524a95 100644
--- a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
+++ b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
@@ -5,6 +5,20 @@
#include
#include "Arduino.h"
+#if defined(__AVR__)
+/*
+ * The datasheet says: a command need > 37us to settle.
+ * Use a delay of 2 us instead of 100 us after each command,
+ * because the overhead of this library seems to be using the other 35 us.
+ * 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
+ */
+# if !defined(DO_NOT_USE_FAST_LCD_TIMING)
+#define USE_FAST_LCD_TIMING
+# endif
+#endif
+
// When the display powers up, it is configured as follows:
//
// 1. Display clear
@@ -21,7 +35,7 @@
// 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
+// can't assume that it is in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
@@ -72,7 +86,7 @@ void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t en
else
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
- begin(16, 1);
+ begin(16, 1); // initializing for a 1601 LCD, but the user must call begin() with the right values at startup. Outcommenting increases program size
}
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
@@ -262,12 +276,14 @@ void LiquidCrystal::noAutoscroll(void) {
// Allows us to fill the first 8 CGRAM locations
// with custom characters
+// This also sets cursor to 0.0
void LiquidCrystal::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]);
}
+ // command(LCD_SETDDRAMADDR); // set cursor to 0.0, this avoids overwriting CGRAM by next write() command. Not contained anymore in the Arduino version
}
/*********** mid level commands, for sending data/cmds */
@@ -278,7 +294,7 @@ inline void LiquidCrystal::command(uint8_t value) {
inline size_t LiquidCrystal::write(uint8_t value) {
send(value, HIGH);
- return 1; // assume sucess
+ return 1; // assume success
}
/************ low level data pushing commands **********/
@@ -306,7 +322,11 @@ void LiquidCrystal::pulseEnable(void) {
digitalWrite(_enable_pin, HIGH);
delayMicroseconds(1); // enable pulse must be >450ns
digitalWrite(_enable_pin, LOW);
+#if defined(USE_FAST_LCD_TIMING)
+ delayMicroseconds(2); // commands need > 37us to settle
+#else
delayMicroseconds(100); // commands need > 37us to settle
+#endif
}
void LiquidCrystal::write4bits(uint8_t value) {
diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp
similarity index 87%
rename from examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp
rename to examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp
index f89c98109..d8de0ef42 100644
--- a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp
+++ b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp
@@ -1,9 +1,20 @@
+// 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.h"
+#define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.hpp"
#endif
#include "LiquidCrystal_I2C.h"
@@ -23,6 +34,18 @@ inline size_t LiquidCrystal_I2C::write(uint8_t value) {
#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
@@ -131,7 +154,11 @@ void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t line
/********** 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);
}
@@ -274,10 +301,13 @@ void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
expanderWrite(_data | En); // En high
- delayMicroseconds(1); // enable pulse must be >450ns
-
+#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
- delayMicroseconds(50); // commands need > 37us to settle
+#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
@@ -342,3 +372,4 @@ void LiquidCrystal_I2C::setContrast(uint8_t new_val) {
}
#pragma GCC diagnostic pop
+#endif // _LIQUID_CRYSTAL_I2C_HPP
diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
+++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/CallbackDemo/CallbackDemo.ino
similarity index 67%
rename from examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino
rename to examples/CallbackDemo/CallbackDemo.ino
index 3c1a3f40a..05342d827 100644
--- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino
+++ b/examples/CallbackDemo/CallbackDemo.ino
@@ -1,14 +1,15 @@
/*
- * SimpleReceiverWithCallback.cpp
+ * CallbackDemo.cpp
*
- * Demonstrates receiving NEC IR codes with IRrecv
+ * Demonstrates receiving NEC IR codes with IRrecv using callback function
+ * Based on SimpleReceiver example
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2022 Armin Joachimsmeyer
+ * 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
@@ -37,8 +38,7 @@
*/
//#define DECODE_DENON // Includes Sharp
//#define DECODE_JVC
-//#define DECODE_KASEIKYO
-//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
+//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes
//#define DECODE_LG
#define DECODE_NEC // Includes Apple and Onkyo
//#define DECODE_SAMSUNG
@@ -59,34 +59,38 @@
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-//#define RAW_BUFFER_LENGTH 180 // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
/*
- * For callback
+ * Callback specific variables and functions
*/
-#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 ReceiveCompleteCallbackHandler();
void setup() {
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_IRREMOTE));
// 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);
Serial.print(F("Ready to receive IR signals of protocols: "));
- printActiveIRProtocols (&Serial);
+ printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
+ Serial.print(F("Using callback function for processing received data"));
+
}
void loop() {
@@ -94,17 +98,24 @@ void loop() {
* Print in loop (interrupts are enabled here) if received data is available.
*/
if (sIRDataJustReceived) {
- // Print a short summary of received data
- IrReceiver.printIRResultShort(&Serial);
- IrReceiver.printIRSendUsage(&Serial);
+ sIRDataJustReceived = false;
+ /*
+ * Print info of the received data
+ */
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
/*
* We have an unknown protocol here, print more info.
- * !!!Attention!!! This prints incorrect values, if we are late (not in this simple example :-))
- * and the the first mark of the next (repeat) data was yet received
+ * This will print incorrect timing values, if we are late (not in this simple example :-))
+ * and the the first mark of the next (repeat) data was yet received.
+ * Therefore we first test for this condition.
*/
- IrReceiver.printIRResultRawFormatted(&Serial, true); //
+ if (!IrReceiver.isIdle()) {
+ IrReceiver.printIRResultRawFormatted(&Serial, true);
+ }
+ } else {
+ IrReceiver.printIRResultShort(&Serial);
+ IrReceiver.printIRSendUsage(&Serial);
}
Serial.println();
}
@@ -113,17 +124,30 @@ void loop() {
/*
* 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.
+ * 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,
+ *
+ * A good practice -but somewhat more complex- is to perform small and time critical actions in the callback function,
+ * copy the relevant data to local variables and signal the receiving to main loop, which in turn processes this data.
+ * This is similar to simply using "if (IrReceiver.decode())", but has the advantage,
+ * that it does not block the receiving of the next IR frame, until the main loop reaches this statement.
*/
#if defined(ESP32) || defined(ESP8266)
IRAM_ATTR
# endif
void ReceiveCompleteCallbackHandler() {
- IrReceiver.decode(); // fill IrReceiver.decodedIRData
+ /*
+ * Fill IrReceiver.decodedIRData
+ */
+ IrReceiver.decode();
+
+ /*
+ * Enable receiving of the next frame.
+ */
+ IrReceiver.resume();
/*
* Check the received data and perform actions according to the received command
@@ -145,14 +169,4 @@ void ReceiveCompleteCallbackHandler() {
* running in ISR (Interrupt Service Routine) context where interrupts are disabled.
*/
sIRDataJustReceived = true;
-
- /*
- * Enable receiving of the next value.
- * !!!Attention!!!
- * After receiving the first mark of the next (repeat) data, 3 variables required for printing are reset/overwritten.
- * - IrReceiver.irparams.rawlen
- * - IrReceiver.irparams.rawbuf[0]
- * - IrReceiver.irparams.OverflowFlag)
- */
- IrReceiver.resume();
}
diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h
similarity index 71%
rename from examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h
rename to examples/CallbackDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h
+++ b/examples/CallbackDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ControlRelay/ControlRelay.ino b/examples/ControlRelay/ControlRelay.ino
index 1460872f4..a475c6771 100644
--- a/examples/ControlRelay/ControlRelay.ino
+++ b/examples/ControlRelay/ControlRelay.ino
@@ -33,9 +33,9 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
-#if FLASHEND <= 0x1FFF || (RAMEND <= 0x4FF || RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167
+#if FLASHEND <= 0x1FFF || RAMSIZE <= 0x400 // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167
#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
#define EXCLUDE_EXOTIC_PROTOCOLS
#endif
@@ -53,7 +53,9 @@ void setup() {
pinMode(RELAY_PIN, 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_attiny3217)
+
+#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
diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ControlRelay/PinDefinitionsAndMore.h
+++ b/examples/ControlRelay/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/IRDispatcherDemo/DemoIRCommandMapping.h b/examples/IRDispatcherDemo/DemoIRCommandMapping.h
index 26110da23..38b344752 100644
--- a/examples/IRDispatcherDemo/DemoIRCommandMapping.h
+++ b/examples/IRDispatcherDemo/DemoIRCommandMapping.h
@@ -1,10 +1,25 @@
/*
* DemoIRCommandMapping.h
*
- * IR remote button codes, strings, and functions to call
+ * Contains IR remote button codes, strings, and the mapping of codes to functions to call by the dispatcher
*
- * Copyright (C) 2019-2022 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2019-2026 Armin Joachimsmeyer
+ *
+ * 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 .
*
*/
@@ -12,15 +27,16 @@
#define _IR_COMMAND_MAPPING_H
#include
-//#include "Commands.h" // includes all the commands used in the mapping arrays below
+
+#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 switched, will be taken as default
+//#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
+#define USE_KEYES_REMOTE_CLONE // the one you can buy at Aliexpress
#endif
#if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE))
@@ -30,11 +46,7 @@
#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
-#if defined(USE_IRMP_LIBRARY)
-#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit
-#else
#define IR_ADDRESS 0x00
-#endif
#define IR_UP 0x18
#define IR_DOWN 0x52
@@ -88,11 +100,7 @@
* 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
-#if defined(USE_IRMP_LIBRARY)
-#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit
-#else
#define IR_ADDRESS 0x00
-#endif
#define IR_UP 0x46
#define IR_DOWN 0x15
@@ -144,7 +152,7 @@
* Main mapping of commands to C functions
*/
-// IR strings of functions for output
+// Strings of commands for Serial output
static const char LEDon[] PROGMEM ="LED on";
static const char LEDoff[] PROGMEM ="LED off";
@@ -161,33 +169,33 @@ static const char printMenu[] PROGMEM ="printMenu";
static const char reset[] PROGMEM ="reset";
static const char stop[] PROGMEM ="stop";
-// not used yet
-static const char test[] PROGMEM ="test";
-static const char pattern[] PROGMEM ="pattern";
-static const char unknown[] PROGMEM ="unknown";
-
/*
* 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, &doLedBlink20times, blink20times }, /**/
-{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop },
+{ 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, which can be executed always
+ * Short commands that can always be executed
*/
-{ COMMAND_TONE1, IR_COMMAND_FLAG_BLOCKING, &doTone1800, tone1800 }, /**/
-{ COMMAND_TONE3, IR_COMMAND_FLAG_BLOCKING, &doPrintMenu, printMenu }, /**/
-{ COMMAND_ON, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOn, LEDon }, /**/
-{ COMMAND_OFF, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOff, LEDoff }, /**/
-{ COMMAND_START, IR_COMMAND_FLAG_NON_BLOCKING, &doLedBlinkStart, blinkStart }, /**/
-{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, reset },
+{ 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, tone2200 }, /**/
-{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, /**/
-{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, decreaseBlink } };
+{ 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
diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.h b/examples/IRDispatcherDemo/IRCommandDispatcher.h
deleted file mode 100644
index e3f46127b..000000000
--- a/examples/IRDispatcherDemo/IRCommandDispatcher.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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-2021 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.
- *
- * ServoEasing 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
-
-/*
- * 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)
-
-// Basic mapping structure
-struct IRToCommandMappingStruct {
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
- uint16_t IRCode;
-#else
- uint8_t IRCode;
-#endif
- uint8_t Flags;
- void (*CommandToCall)();
- const char *CommandString;
-};
-
-struct IRDataForCommandDispatcherStruct {
- uint16_t address; // to distinguish between multiple senders
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
- uint16_t command;
-#else
- uint8_t command;
-#endif
- bool isRepeat;
- 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.
-};
-
-/*
- * Special codes (hopefully) not sent by the remote - otherwise please redefine it here
- */
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
-#define COMMAND_EMPTY 0xFFFF // code no command
-#else
-#define COMMAND_EMPTY 0xFF // code no command
-#endif
-
-#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return
-#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break
-#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return
-
-class IRCommandDispatcher {
-public:
- void init();
-
- bool checkAndRunNonBlockingCommands();
- bool checkAndRunSuspendedBlockingCommands();
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
- void setNextBlockingCommand(uint16_t aBlockingCommandToRunNext);
-#else
- void setNextBlockingCommand(uint8_t aBlockingCommandToRunNext);
-#endif
- bool delayAndCheckForStop(uint16_t aDelayMillis);
-
- // The main dispatcher function
- void checkAndCallCommand(bool aCallBlockingCommandImmediately);
-
- void printIRCommandString(Print *aSerial);
- void setRequestToStopReceived(bool aRequestToStopReceived = true);
-
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
- uint16_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command
- uint16_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop
- uint16_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
-#else
- uint8_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command
- uint8_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop
- uint8_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
-#endif
- 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).
- * Is reset by next IR command received. Can be reset by main loop, if command has stopped.
- */
- 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
diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp
deleted file mode 100644
index f2bc25982..000000000
--- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * 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-2022 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.
- *
- * ServoEasing 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_HPP
-#define _IR_COMMAND_DISPATCHER_HPP
-
-#include
-
-#include "IRCommandDispatcher.h"
-
-/*
- * 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(INFO) && !defined(LOCAL_INFO)
-#define LOCAL_INFO
-#else
-//#define LOCAL_INFO // This enables info output only for this file
-#endif
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
-#define LOCAL_DEBUG
-// Propagate debug level
-#define LOCAL_INFO
-#else
-//#define LOCAL_DEBUG // This enables debug output only for this file
-#endif
-
-IRCommandDispatcher IRDispatcher;
-
-#if defined(USE_TINY_IR_RECEIVER)
-#include "TinyIRReceiver.hpp" // included in "IRremote" library
-
-#if defined(LOCAL_INFO)
-#define CD_INFO_PRINT(...) Serial.print(__VA_ARGS__);
-#define CD_INFO_PRINTLN(...) Serial.println(__VA_ARGS__);
-#else
-#define CD_INFO_PRINT(...) void();
-#define CD_INFO_PRINTLN(...) void();
-#endif
-
-void IRCommandDispatcher::init() {
- initPCIInterruptForTinyReceiver();
-}
-
-/*
- * This is the TinyReceiver callback function, which is called if a complete command was received
- * It checks for right address and then call the dispatcher
- */
-#if defined(ESP8266) || defined(ESP32)
-IRAM_ATTR
-#endif
-void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) {
- IRDispatcher.IRReceivedData.address = aAddress;
- IRDispatcher.IRReceivedData.command = aCommand;
- IRDispatcher.IRReceivedData.isRepeat = aFlags & IRDATA_FLAGS_IS_REPEAT;
- IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
-
- CD_INFO_PRINT(F("A=0x"));
- CD_INFO_PRINT(aAddress, HEX);
- CD_INFO_PRINT(F(" C=0x"));
- CD_INFO_PRINT(aCommand, HEX);
- if (IRDispatcher.IRReceivedData.isRepeat) {
- CD_INFO_PRINT(F("R"));
- }
- CD_INFO_PRINTLN();
-
- if (aAddress == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
- IRDispatcher.IRReceivedData.isAvailable = true;
- 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);
- }
-
- } else {
- CD_INFO_PRINT(F("Wrong address. Expected 0x"));
- CD_INFO_PRINTLN(IR_ADDRESS, HEX);
- }
-}
-
-#elif defined(USE_IRMP_LIBRARY)
-# if !defined(IRMP_USE_COMPLETE_CALLBACK)
-# error IRMP_USE_COMPLETE_CALLBACK must be activated for IRMP library
-# endif
-
-void IRCommandDispatcher::init() {
- irmp_init();
-}
-
-/*
- * This is the callback function, which is called if a complete command was received
- */
-#if defined(ESP8266) || defined(ESP32)
-IRAM_ATTR
-#endif
-void handleReceivedIRData() {
- IRMP_DATA tTeporaryData;
- irmp_get_data(&tTeporaryData);
- IRDispatcher.IRReceivedData.address = tTeporaryData.address;
- IRDispatcher.IRReceivedData.command = tTeporaryData.command;
- IRDispatcher.IRReceivedData.isRepeat = tTeporaryData.flags & IRMP_FLAG_REPETITION;
- IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
-
- CD_INFO_PRINT(F("A=0x"));
- CD_INFO_PRINT(IRDispatcher.IRReceivedData.address, HEX);
- CD_INFO_PRINT(F(" C=0x"));
- CD_INFO_PRINT(IRDispatcher.IRReceivedData.command, HEX);
- if (IRDispatcher.IRReceivedData.isRepeat) {
- CD_INFO_PRINT(F("R"));
- }
- CD_INFO_PRINTLN();
-
- // To enable delay() for commands
-# if !defined(ARDUINO_ARCH_MBED)
- interrupts(); // be careful with always executable commands which lasts longer than the IR repeat duration.
-# endif
-
- if (IRDispatcher.IRReceivedData.address == IR_ADDRESS) {
- IRDispatcher.checkAndCallCommand(true);
- } else {
- CD_INFO_PRINT(F("Wrong address. Expected 0x"));
- CD_INFO_PRINTLN(IR_ADDRESS, HEX);
- }
-}
-#endif // elif defined(USE_IRMP_LIBRARY)
-
-/*
- * The main dispatcher function
- * Sets flags justCalledRegularIRCommand, executingBlockingCommand
- * @param aCallBlockingCommandImmediately Run blocking command directly, otherwise set request to stop to true
- * and store command for main loop to execute by checkAndRunSuspendedBlockingCommands().
- * Should be false if called by ISR.
- */
-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)
- const __FlashStringHelper *tCommandName = reinterpret_cast(IRMapping[i].CommandString);
-#endif
- /*
- * Check for repeat and if repeat is allowed for the current command
- */
- if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Repeats of command \""));
- Serial.print(tCommandName);
- Serial.println("\" not accepted");
-#endif
- return;
- }
-
- /*
- * Do not accept recursive call of the same command
- */
- if (currentBlockingCommandCalled == IRReceivedData.command) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Recursive command \""));
- Serial.print(tCommandName);
- Serial.println("\" not accepted");
-#endif
- return;
- }
-
- /*
- * lets start a new turn
- */
- requestToStopReceived = false;
-
- bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING);
- if (tIsNonBlockingCommand) {
- // short command here, just call
- CD_INFO_PRINT(F("Run non blocking command: "));
- CD_INFO_PRINTLN (tCommandName);
- IRMapping[i].CommandToCall();
- } else {
- if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) {
- /*
- * here we are called from main loop to execute a command
- */
- 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!!!
- */
- CD_INFO_PRINT(F("Run blocking command: "));
- CD_INFO_PRINTLN (tCommandName);
-
- IRMapping[i].CommandToCall();
-#if defined(TRACE)
- Serial.println(F("End of blocking command"));
-#endif
- currentBlockingCommandCalled = COMMAND_EMPTY;
- } else {
- /*
- * Do not run command directly, but set request to stop to true and store command for main loop to execute
- */
- BlockingCommandToRunNext = IRReceivedData.command;
- requestToStopReceived = true; // to stop running command
- CD_INFO_PRINT(F("Requested stop and stored blocking command "));
- CD_INFO_PRINT (tCommandName);
- CD_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) {
-
- CD_INFO_PRINT(F("Take stored command = 0x"));
- CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX);
-
- IRReceivedData.command = BlockingCommandToRunNext;
- BlockingCommandToRunNext = COMMAND_EMPTY;
- IRReceivedData.isRepeat = false;
- checkAndCallCommand(true);
- return true;
- }
- return false;
-}
-
-#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
-void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunNext)
-#else
-void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext)
-#endif
- {
- CD_INFO_PRINT(F("Set next command to 0x"));
- CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX);
- 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::printIRCommandString(Print *aSerial) {
- aSerial->print(F("IRCommand="));
- for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
- if (IRReceivedData.command == IRMapping[i].IRCode) {
- aSerial->println(reinterpret_cast(IRMapping[i].CommandString));
- return;
- }
- }
- aSerial->println(reinterpret_cast(unknown));
-}
-
-void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) {
- requestToStopReceived = aRequestToStopReceived;
-}
-
-#if defined(LOCAL_DEBUG)
-#undef LOCAL_DEBUG
-#endif
-#if defined(LOCAL_INFO)
-#undef LOCAL_INFO
-#endif
-#endif // _IR_COMMAND_DISPATCHER_HPP
diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino
index 8a66d4fc8..3ec5d8b81 100644
--- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino
+++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino
@@ -1,10 +1,9 @@
/*
* IRDispatcherDemo.cpp
*
- * Receives NEC IR commands and maps them to different actions by means of a mapping array.
+ * 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-2021 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2020-2026 Armin Joachimsmeyer
*
* 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.
@@ -29,83 +28,37 @@
/*
* Choose the library to be used for IR receiving
*/
-#define USE_TINY_IR_RECEIVER // Recommended, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
-//#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Requires additional 112 bytes program memory + 4 bytes RAM
-
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
-// Some kind of auto detect library if USE_TINY_IR_RECEIVER is deactivated
-#if !defined(USE_TINY_IR_RECEIVER)
-# if defined(IR_RECEIVE_PIN)
-#define USE_TINY_IR_RECEIVER
-# elif !defined(USE_IRMP_LIBRARY) && defined(IRMP_INPUT_PIN)
-#define USE_IRMP_LIBRARY
-# else
-#error No IR library selected
-# endif
+//#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. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+
+#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
-
-//#define NO_LED_FEEDBACK_CODE // You can set it here, before the include of IRCommandDispatcher below
-
-#if defined(USE_TINY_IR_RECEIVER)
-//#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.
-
-/*
- * Set sensible receive pin for different CPU's
- */
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
-#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
-#define IR_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
-# else
-#define IR_INPUT_PIN 0 // PCINT0
-# endif
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
-#define IR_INPUT_PIN 10
-# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
-#define IR_INPUT_PIN 21 // INT0
-# elif defined(ESP8266)
-#define IR_INPUT_PIN 14 // D5
-# elif defined(ESP32)
-#define IR_INPUT_PIN 15
-# elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
-#define IR_INPUT_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
-# elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
-#define IR_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
-# else
-#define IR_INPUT_PIN 2 // INT0
-# endif
-
-#elif defined(USE_IRMP_LIBRARY)
-/*
- * IRMP version
- */
-#define IR_INPUT_PIN 2
-#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used.
-#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
-#define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
+#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
-//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory
-
-#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some program memory. Must before #include
-
+#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
-
-# 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
-void handleReceivedIRData();
-void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration);
-#endif // #if defined(USE_IRMP_LIBRARY)
+//#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();
@@ -119,23 +72,20 @@ void doTone1800();
void doTone2200();
/*
- * Set definitions and include IRCommandDispatcher library after the declaration of all commands to map
+ * Set definitions and include IRCommandDispatcher library after the declaration of all commands required for mapping
*/
-#define INFO // to see some informative output
-#include "IRCommandDispatcher.h" // Only for required declarations, the library itself is included below after the definitions of the commands
-#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown".
-#include "IRCommandDispatcher.hpp"
+#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
-/*
- * Helper macro for getting a macro definition as string
- */
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration);
-void setup() {
+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_attiny3217)
+
+#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)
@@ -144,45 +94,36 @@ void setup() {
// 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"));
+ 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)
- // play feedback tone before setup, since it kills the IR timer settings
+#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 just calls irmp_init()
-#if defined(USE_TINY_IR_RECEIVER)
- Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN)));
-#else
- irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp
-
- 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(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
-#endif
+ IRDispatcher.init(); // This calls the init function of the chosen library
+ IRDispatcher.printIRInfo(&Serial);
- Serial.print(F("Listening to commands of IR remote of type "));
- Serial.println(IR_REMOTE_NAME);
doPrintMenu();
+#if defined(DEBUG) && defined(SP)
+ Serial.print(F("SP=0x"));
+ Serial.println(SP, HEX);
+#endif
}
-void loop() {
+void loop()
+{
IRDispatcher.checkAndRunSuspendedBlockingCommands();
- if (doBlink) {
+ if (doBlink)
+ {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
digitalWrite(LED_BUILTIN, LOW);
@@ -191,15 +132,22 @@ void loop() {
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 += 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);
}
-void doPrintMenu(){
+/*
+ * 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"));
@@ -217,39 +165,50 @@ void doPrintMenu(){
/*
* Here the actions that are matched to IR keys
*/
-void doLedOn() {
+void doLedOn()
+{
digitalWrite(LED_BUILTIN, HIGH);
doBlink = false;
}
-void doLedOff() {
+void doLedOff()
+{
digitalWrite(LED_BUILTIN, LOW);
doBlink = false;
}
-void doIncreaseBlinkFrequency() {
+void doIncreaseBlinkFrequency()
+{
doBlink = true;
- if (sBlinkDelay > 5) {
+ if (sBlinkDelay > 5)
+ {
sBlinkDelay -= sBlinkDelay / 4;
}
}
-void doDecreaseBlinkFrequency() {
+void doDecreaseBlinkFrequency()
+{
doBlink = true;
sBlinkDelay += sBlinkDelay / 4;
}
-void doStop() {
+void doStop()
+{
doBlink = false;
+ digitalWrite(LED_BUILTIN, LOW);
}
-void doResetBlinkFrequency() {
+void doResetBlinkFrequency()
+{
sBlinkDelay = 200;
digitalWrite(LED_BUILTIN, LOW);
}
-void doLedBlinkStart() {
+void doLedBlinkStart()
+{
doBlink = true;
}
/*
- * This is a blocking function and checks periodically for stop
+ * This is a blocking function which checks for stop
*/
-void doLedBlink20times() {
- for (int i = 0; i < 20; ++i) {
+void doLedBlink20times()
+{
+ for (int i = 0; i < 20; ++i)
+ {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(200);
digitalWrite(LED_BUILTIN, LOW);
@@ -257,50 +216,63 @@ void doLedBlink20times() {
}
}
-
-void doTone1800() {
-#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
- irmp_tone(TONE_PIN, 1800, 200);
-#else
-# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
- tone(TONE_PIN, 1800, 200);
-# endif
+/*
+ * Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled
+ */
+void doTone1800()
+{
+#if defined(TONE_PIN)
+ IRremoteTone(TONE_PIN, 1800, 200);
#endif
}
-void doTone2200() {
-#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
- // use IRMP compatible function for tone()
- irmp_tone(TONE_PIN, 2200, 50);
-#else
-# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266
- tone(TONE_PIN, 2200, 50);
-# endif
+/*
+ * Lasts 50 ms and allows receiving of repeats
+ */
+void doTone2200()
+{
+#if defined(TONE_PIN)
+ IRremoteTone(TONE_PIN, 2200, 50);
#endif
}
-#if defined(USE_IRMP_LIBRARY)
/*
- * Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated
+ * 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 irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
-# if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
+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();
- tone(_pin, frequency, 0);
- if (duration == 0) {
- duration = 100;
+# endif
+ tone(aTonePin, aFrequency, 0);
+ if (aDuration == 0)
+ {
+ aDuration = 100;
}
- delay(duration);
- noTone(_pin);
+ delay(aDuration);
+ noTone(aTonePin);
+# if defined(USE_IRREMOTE_LIBRARY)
+ IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
+# else
restoreIRTimer();
-#elif defined(ESP8266)
- // tone() stops timer 1
- (void) _pin;
- (void) frequency;
- (void) duration;
-#else
- tone(_pin, frequency, duration);
+# endif
+# endif
#endif
}
-#endif // #if defined(USE_IRMP_LIBRARY)
diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
+++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
index 328db5b8d..a110d8fb5 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2021 Armin Joachimsmeyer
+ * Copyright (c) 2021-2025 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
@@ -31,11 +31,36 @@
*/
#include
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+
+/*
+ * !!! The value of RAW_BUFFER_LENGTH (and some other macros) must be the same in all compile units !!!
+ * Otherwise you may get warnings like "type 'struct IRData' itself violates the C++ One Definition Rule"
+ */
+#if !defined(RAW_BUFFER_LENGTH)
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
+# else
+// Here we most likely have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 750
+# endif
+#endif
+
#include "IRremoteExtensionClass.h"
IRExtensionClass::IRExtensionClass(IRrecv *aIrReceiver) {
MyIrReceiver = aIrReceiver;
}
+bool IRExtensionClass::decode() {
+ return MyIrReceiver->decode();
+}
+
+bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) {
+ return MyIrReceiver->printIRResultShort(aSerial, aCheckForRecordGapsMicros);
+}
+
void IRExtensionClass::resume() {
Serial.println(F("Call resume()"));
MyIrReceiver->resume();
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
index 5c50fd5e4..07c858802 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2021 Armin Joachimsmeyer
+ * Copyright (c) 2021-2025 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
@@ -39,6 +39,8 @@ class IRExtensionClass
public:
IRrecv * MyIrReceiver;
IRExtensionClass(IRrecv * aIrReceiver);
+ bool decode();
+ bool printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros = true);
void resume();
};
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
index 65b42c03c..9ee1e437b 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
@@ -30,15 +30,16 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
-#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Here we most likely have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 750
# endif
#endif
@@ -53,8 +54,15 @@ IRExtensionClass IRExtension(&IrReceiver);
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_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!
+
+#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_IRREMOTE));
@@ -62,7 +70,6 @@ void setup() {
// 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);
-
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
@@ -70,8 +77,8 @@ void setup() {
}
void loop() {
- if (IrReceiver.decode()) {
- IrReceiver.printIRResultShort(&Serial);
+ if (IRExtension.decode()) {
+ IRExtension.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
IRExtension.resume(); // Use the extended function provided by IRExtension class
}
diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
+++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino
index 22ae75fbb..7f8ef9e32 100644
--- a/examples/IRremoteInfo/IRremoteInfo.ino
+++ b/examples/IRremoteInfo/IRremoteInfo.ino
@@ -11,6 +11,8 @@
*/
#include
+//#define DEBUG
+
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 240 bytes program memory if IrSender.write is used
//#define SEND_PWM_BY_TIMER
//#define USE_NO_SEND_PWM
@@ -34,9 +36,17 @@ void dumpFooter();
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_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!
+
+#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_IRREMOTE));
@@ -193,7 +203,7 @@ void dumpPulseParams() {
;
Serial.println(F(" uSecs"));
Serial.print(F("Measurement tolerance: "));
- Serial.print(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING);
+ Serial.print(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT);
Serial.println(F("%"));
}
@@ -205,7 +215,7 @@ void dumpSignalParams() {
void dumpDebugMode() {
Serial.print(F("Debug Mode: "));
-#if DEBUG
+#if defined(DEBUG)
Serial.println(F("ON"));
#else
Serial.println(F("OFF (Normal)"));
@@ -259,13 +269,6 @@ void dumpProtocols() {
Serial.println(F("Disabled"));
#endif
- Serial.print(F("PANASONIC: "));
-#if defined(DECODE_PANASONIC)
- Serial.println(F("Enabled"));
-#else
- Serial.println(F("Disabled"));
-#endif
-
Serial.print(F("JVC: "));
#if defined(DECODE_JVC)
Serial.println(F("Enabled"));
diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino
index a840bf240..7af892c10 100644
--- a/examples/MicroGirs/MicroGirs.ino
+++ b/examples/MicroGirs/MicroGirs.ino
@@ -64,15 +64,16 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
-#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Here we most likely have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 750
# endif
#endif
@@ -83,6 +84,8 @@
#define BAUDRATE 115200
#define NO_DECODER
+//#define NO_LED_FEEDBACK_CODE // Saves 346 bytes program memory
+
#include "IRremote.hpp"
#include
@@ -190,8 +193,7 @@ String Tokenizer::getRest() {
}
String Tokenizer::getLine() {
- if (index == invalidIndex)
- return String("");
+ if (index == invalidIndex) return String("");
int i = payload.indexOf('\n', index);
String s = (i > 0) ? payload.substring(index, i) : payload.substring(index);
@@ -200,16 +202,13 @@ String Tokenizer::getLine() {
}
String Tokenizer::getToken() {
- if (index < 0)
- return String("");
+ if (index < 0) return String("");
int i = payload.indexOf(' ', index);
String s = (i > 0) ? payload.substring(index, i) : payload.substring(index);
index = (i > 0) ? i : invalidIndex;
- if (index != invalidIndex)
- if (index != invalidIndex)
- while (payload.charAt(index) == ' ')
- index++;
+ if (index != invalidIndex) if (index != invalidIndex) while (payload.charAt(index) == ' ')
+ index++;
return s;
}
@@ -253,26 +252,23 @@ static inline unsigned hz2khz(frequency_t hz) {
*/
static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, const microseconds_t repeat[], unsigned lengthRepeat,
const microseconds_t ending[], unsigned lengthEnding, frequency_t frequency, unsigned times) {
- if (lengthIntro > 0U)
- IrSender.sendRaw(intro, lengthIntro, hz2khz(frequency));
- if (lengthRepeat > 0U)
- for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++)
- IrSender.sendRaw(repeat, lengthRepeat, hz2khz(frequency));
- if (lengthEnding > 0U)
- IrSender.sendRaw(ending, lengthEnding, hz2khz(frequency));
+ if (lengthIntro > 0U) IrSender.sendRaw(intro, lengthIntro, hz2khz(frequency));
+ if (lengthRepeat > 0U) for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++)
+ IrSender.sendRaw(repeat, lengthRepeat, hz2khz(frequency));
+ if (lengthEnding > 0U) IrSender.sendRaw(ending, lengthEnding, hz2khz(frequency));
}
#endif // TRANSMIT
#if defined(RECEIVE)
static void dump(Stream &stream) {
- unsigned int count = IrReceiver.decodedIRData.rawDataPtr->rawlen;
+ unsigned int count = IrReceiver.irparams.rawlen;
// If buffer gets full, count = RAW_BUFFER_LENGTH, which is odd,
// and IrScrutinizer does not like that.
count &= ~1;
for (unsigned int i = 1; i < count; i++) {
stream.write(i & 1 ? '+' : '-');
- stream.print(IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK, DEC);
+ stream.print(IrReceiver.irparams.rawbuf[i] * MICROS_PER_TICK, DEC);
stream.print(" ");
}
stream.print('-');
@@ -300,8 +296,6 @@ static void receive(Stream &stream) {
*/
void setup() {
Serial.begin(BAUDRATE);
- while (!Serial)
- ; // wait for serial port to connect.
Serial.println(F(PROGNAME " " VERSION));
// Just to know which program is running on my Arduino
@@ -317,9 +311,13 @@ void setup() {
#endif
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
#else
- IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
+ IrSender.begin(3); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
}
diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/MicroGirs/PinDefinitionsAndMore.h
+++ b/examples/MicroGirs/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino
new file mode 100644
index 000000000..c60b990c3
--- /dev/null
+++ b/examples/MultipleReceivers/MultipleReceivers.ino
@@ -0,0 +1,152 @@
+/*
+ * MultipleReceivers.cpp
+ *
+ * Demonstrates receiving from multiple receivers at different pins using multiple IRreceiver instances
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ ************************************************************************************
+ * MIT License
+ *
+ * Copyright (c) 2025-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
+
+#define IR_RECEIVE_PIN_OF_SECOND_RECEIVER 5
+
+/*
+ * Specify which protocol(s) should be used for decoding.
+ * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
+ * This must be done before the #include
+ */
+//#define DECODE_DENON // Includes Sharp
+//#define DECODE_JVC
+//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes
+//#define DECODE_LG
+//#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
+//#define DECODE_SAMSUNG
+//#define DECODE_SONY
+//#define DECODE_RC5
+//#define DECODE_RC6
+//#define DECODE_BOSEWAVE
+//#define DECODE_LEGO_PF
+//#define DECODE_MAGIQUEST
+//#define DECODE_WHYNTER
+//#define DECODE_FAST
+//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
+//#define DECODE_HASH // special decoder for all protocols
+//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
+//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
+#define SUPPORT_MULTIPLE_RECEIVER_INSTANCES
+void UserIRReceiveTimerInterruptHandler(); // Is defined below and must be declared before line #include
+
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+#include // include the library
+
+IRrecv MySecondIrReceiver(IR_RECEIVE_PIN_OF_SECOND_RECEIVER); // This sets the pin for the second instance
+
+void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance);
+
+void setup() {
+ 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_IRREMOTE));
+
+ // 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); // This sets the pin for the default / first instance and enables the global LED feedback
+
+ Serial.print(F("Ready to receive IR signals of protocols: "));
+ printActiveIRProtocols(&Serial);
+ Serial.println(F("at pin " STR(IR_RECEIVE_PIN) " and pin " STR(IR_RECEIVE_PIN_OF_SECOND_RECEIVER)));
+}
+
+void loop() {
+ /*
+ * Check if received data is available and if yes, try to decode it.
+ * Decoded result is in the IrReceiver.decodedIRData structure.
+ *
+ * E.g. command is in IrReceiver.decodedIRData.command
+ * address is in command is in IrReceiver.decodedIRData.address
+ * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
+ */
+ if (IrReceiver.decode()) {
+ handleSuccessfulDecoding(&IrReceiver);
+ }
+ if (MySecondIrReceiver.decode()) {
+ handleSuccessfulDecoding(&MySecondIrReceiver);
+ }
+}
+
+void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance) {
+
+ Serial.print(F("Receiver at pin "));
+ Serial.print(aIRReceiverInstance->irparams.IRReceivePin);
+ Serial.print(F(": "));
+
+ /*
+ * Print a summary of received data
+ */
+ if (aIRReceiverInstance->decodedIRData.protocol == UNKNOWN) {
+ Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
+ // We have an unknown protocol here, print extended info
+ aIRReceiverInstance->printIRResultRawFormatted(&Serial, true);
+
+ aIRReceiverInstance->resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
+ } else {
+ aIRReceiverInstance->resume(); // Early enable receiving of the next IR frame
+
+ aIRReceiverInstance->printIRResultShort(&Serial);
+ aIRReceiverInstance->printIRSendUsage(&Serial);
+ }
+ Serial.println();
+
+ /*
+ * Finally, check the received data and perform actions according to the received command
+ */
+ if (aIRReceiverInstance->decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (aIRReceiverInstance->decodedIRData.command == 0x10) {
+ Serial.println(F("Received command 0x10."));
+ // do something
+ } else if (aIRReceiverInstance->decodedIRData.command == 0x11) {
+ Serial.println(F("Received command 0x11."));
+ // do something else
+ }
+ }
+
+}
+
+/*
+ * If SUPPORT_MULTIPLE_RECEIVER_INSTANCES is active, this handler is called in ISR context after IrReceiver.ReceiveInterruptHandler().
+ * Here we just call the standard ReceiveInterruptHandler for the second receiver.
+ * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving.
+ */
+#if defined(ESP8266) || defined(ESP32)
+IRAM_ATTR
+#endif
+void UserIRReceiveTimerInterruptHandler() {
+ MySecondIrReceiver.ReceiveInterruptHandler();
+}
diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..d3dd74992
--- /dev/null
+++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h
@@ -0,0 +1,366 @@
+/*
+ * 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
+ *
+ * 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)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
+#endif
+
+#if !defined (FLASHEND)
+#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
+#endif
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
+#endif
+#if !defined (RAMSIZE)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
+#endif
diff --git a/examples/MultipleSendPins/MultipleSendPins.ino b/examples/MultipleSendPins/MultipleSendPins.ino
new file mode 100644
index 000000000..ce7b7827a
--- /dev/null
+++ b/examples/MultipleSendPins/MultipleSendPins.ino
@@ -0,0 +1,95 @@
+/*
+ * MultipleSendPins.cpp
+ *
+ * Demonstrates sending IR codes toggling between 2 different send pins.
+ * Based on SimpleSender.
+ *
+ * Copyright (C) 2025 Armin Joachimsmeyer
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ * MIT License
+ */
+#include
+
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+
+//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 52 bytes program memory
+
+#include // include the library
+
+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_IRREMOTE));
+ Serial.print(F("Send IR signals alternating at pin 3 and 4"));
+
+ /*
+ * The IR library setup. That's all!
+ */
+ IrSender.begin(3); // Start with pin3 as send pin and enable feedback LED at default feedback LED pin
+ disableLEDFeedback(); // Disable feedback LED at default feedback LED pin
+}
+
+/*
+ * Set up the data to be sent.
+ * For most protocols, the data is build up with a constant 8 (or 16 byte) address
+ * and a variable 8 bit command.
+ * There are exceptions like Sony and Denon, which have 5 bit address.
+ */
+uint8_t sCommand = 0x34;
+uint8_t sRepeats = 0;
+
+void loop() {
+ /*
+ * Print current send values
+ */
+ Serial.println();
+ Serial.print(F("Send now: address=0x00, command=0x"));
+ Serial.print(sCommand, HEX);
+ Serial.print(F(", repeats="));
+ Serial.print(sRepeats);
+ Serial.println();
+
+ Serial.println(F("Send standard NEC with 8 bit address"));
+ Serial.flush();
+
+ // Receiver output for the first loop must be: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
+ IrSender.sendNEC(0x00, sCommand, sRepeats);
+
+ /*
+ * If you want to send a raw HEX value directly like e.g. 0xCB340102 you must use sendNECRaw()
+ */
+// Serial.println(F("Send 32 bit LSB 0xCB340102 with NECRaw()"));
+// IrSender.sendNECRaw(0xCB340102, sRepeats);
+ /*
+ * If you want to send an "old" MSB HEX value used by IRremote versions before 3.0 like e.g. 0x40802CD3 you must use sendNECMSB()
+ */
+// Serial.println(F("Send old 32 bit MSB 0x40802CD3 with sendNECMSB()"));
+// IrSender.sendNECMSB(0x40802CD3, 32, sRepeats);
+ /*
+ * Increment send values
+ */
+ sCommand += 0x11;
+ sRepeats++;
+ // clip repeats at 4
+ if (sRepeats > 4) {
+ sRepeats = 4;
+ }
+
+ /*
+ * Toggle between send pin 3 and 4
+ */
+ if (IrSender.sendPin == 3) {
+ IrSender.setSendPin(4);
+ } else {
+ IrSender.setSendPin(3);
+ }
+ delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
+}
diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h
+++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino
index fdd4eaf36..faae9a06e 100644
--- a/examples/ReceiveAndSend/ReceiveAndSend.ino
+++ b/examples/ReceiveAndSend/ReceiveAndSend.ino
@@ -14,6 +14,7 @@
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
+ * See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSend_Code
*
* Initially coded 2009 Ken Shirriff http://www.righto.com
*
@@ -22,7 +23,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2009-2023 Ken Shirriff, Armin Joachimsmeyer
+ * Copyright (c) 2009-2026 Ken Shirriff, 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
@@ -45,8 +46,6 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
-
/*
* Specify which protocol(s) should be used for decoding.
* If no protocol is defined, all protocols (except Bang&Olufsen) are active.
@@ -54,10 +53,9 @@
*/
//#define DECODE_DENON // Includes Sharp
//#define DECODE_JVC
-//#define DECODE_KASEIKYO
-//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
+//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes
//#define DECODE_LG
-#define DECODE_NEC // Includes Apple and Onkyo
+//#define DECODE_NEC // Includes Apple and Onkyo
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
@@ -69,29 +67,39 @@
//#define DECODE_WHYNTER
//#define DECODE_FAST
//
+
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 120
-# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO
-#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
+// Here we most likely have 2 k RAM or more
#define RAW_BUFFER_LENGTH 750
# endif
#endif
+#if RAMSIZE >= 0x1000
+// Here we most likely have 4 k RAM or more
+#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve timing values above 12750 us
+#endif
+
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
-//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 202 bytes program memory
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
int SEND_BUTTON_PIN = APPLICATION_PIN;
@@ -103,7 +111,7 @@ struct storedIRDataStruct {
IRData receivedIRData;
// extensions for sendRaw
uint8_t rawCode[RAW_BUFFER_LENGTH]; // The durations if raw
- uint8_t rawCodeLength; // The length of the code
+ uint16_t rawCodeLength; // The length of the code
} sStoredIRData;
bool sSendButtonWasActive;
@@ -115,7 +123,9 @@ void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
+
+#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
@@ -127,9 +137,14 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
- Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
- Serial.println(SEND_BUTTON_PIN);
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
+ Serial.print(F("Ready to send IR signal (with repeats) at pin " STR(IR_SEND_PIN) " as long as button at pin "));
+ Serial.print(SEND_BUTTON_PIN);
+ Serial.println(F(" is pressed."));
}
void loop() {
@@ -166,6 +181,7 @@ void loop() {
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
+ delay(100); // Button debouncing
} else if (IrReceiver.decode()) {
/*
@@ -176,15 +192,14 @@ void loop() {
}
sSendButtonWasActive = tSendButtonIsActive;
- delay(100);
}
// Stores the code for later playback in sStoredIRData
// Most of this code is just logging
void storeCode() {
- if (IrReceiver.decodedIRData.rawDataPtr->rawlen < 4) {
+ if (IrReceiver.irparams.rawlen < 4) {
Serial.print(F("Ignore data with rawlen="));
- Serial.println(IrReceiver.decodedIRData.rawDataPtr->rawlen);
+ Serial.println(IrReceiver.irparams.rawlen);
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
@@ -199,21 +214,31 @@ void storeCode() {
Serial.println(F("Ignore parity error"));
return;
}
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
+ Serial.println(F("Overflow occurred, raw data did not fit into " STR(RAW_BUFFER_LENGTH) " byte raw buffer"));
+ return;
+ }
/*
* Copy decoded data
*/
sStoredIRData.receivedIRData = IrReceiver.decodedIRData;
- if (sStoredIRData.receivedIRData.protocol == UNKNOWN) {
- Serial.print(F("Received unknown code and store "));
- Serial.print(IrReceiver.decodedIRData.rawDataPtr->rawlen - 1);
- Serial.println(F(" timing entries as raw "));
- IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
- sStoredIRData.rawCodeLength = IrReceiver.decodedIRData.rawDataPtr->rawlen - 1;
+ auto tProtocol = sStoredIRData.receivedIRData.protocol;
+ if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE) {
+ // TODO: support PULSE_WIDTH and PULSE_DISTANCE with IrSender.write
+ sStoredIRData.rawCodeLength = IrReceiver.irparams.rawlen - 1;
/*
* Store the current raw data in a dedicated array for later usage
*/
IrReceiver.compensateAndStoreIRResultInArray(sStoredIRData.rawCode);
+ /*
+ * Print info
+ */
+ Serial.print(F("Received unknown or pulse width/distance code and store "));
+ Serial.print(IrReceiver.irparams.rawlen - 1);
+ Serial.println(F(" timing entries as raw in buffer of size " STR(RAW_BUFFER_LENGTH)));
+ IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
+
} else {
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
@@ -223,7 +248,8 @@ void storeCode() {
}
void sendCode(storedIRDataStruct *aIRDataToSend) {
- if (aIRDataToSend->receivedIRData.protocol == UNKNOWN /* i.e. raw */) {
+ auto tProtocol = aIRDataToSend->receivedIRData.protocol;
+ if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE /* i.e. raw */) {
// Assume 38 KHz
IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38);
@@ -231,12 +257,11 @@ void sendCode(storedIRDataStruct *aIRDataToSend) {
Serial.print(aIRDataToSend->rawCodeLength);
Serial.println(F(" marks or spaces"));
} else {
-
/*
* Use the write function, which does the switch for different protocols
*/
IrSender.write(&aIRDataToSend->receivedIRData);
- printIRResultShort(&Serial, &aIRDataToSend->receivedIRData, false);
+ printIRDataShort(&Serial, &aIRDataToSend->receivedIRData);
}
}
diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
+++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
index 5c2e73556..9f79eac29 100644
--- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
+++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
@@ -16,13 +16,14 @@
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
+ * See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSendDistanceWidth_Code
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2023 Armin Joachimsmeyer
+ * Copyright (c) 2023-2025 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
@@ -45,33 +46,33 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
-#if !defined(IR_SEND_PIN)
-#define IR_SEND_PIN 3
-#endif
-
/*
* Specify DistanceWidthProtocol for decoding. This must be done before the #include
*/
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 120
-# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO
-#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
+// Here we most likely have 2 k RAM or more
#define RAW_BUFFER_LENGTH 750
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 218 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 82 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 58 bytes program memory
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
#define SEND_BUTTON_PIN APPLICATION_PIN
@@ -79,8 +80,8 @@
#define DELAY_BETWEEN_REPEATS_MILLIS 70
// Storage for the recorded code, pre-filled with NEC data
-IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // address 0x12 command 0x34
-DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // NEC timing
+IRDecodedRawDataType sDecodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34
+DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing
uint8_t sNumberOfBits = 32;
bool sSendButtonWasActive;
@@ -89,7 +90,9 @@ void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
+
+#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
@@ -99,7 +102,11 @@ void setup() {
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}
@@ -173,7 +180,12 @@ void loop() {
if (sDecodedRawDataArray[0] != IrReceiver.decodedIRData.decodedRawDataArray[0]) {
*sDecodedRawDataArray = *IrReceiver.decodedIRData.decodedRawDataArray; // copy content here
Serial.print(F("Store new sDecodedRawDataArray[0]=0x"));
+# if (__INT_WIDTH__ < 32)
Serial.println(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
+# else
+ PrintULL::print(&Serial, IrReceiver.decodedIRData.decodedRawDataArray[0], HEX);
+# endif
+
}
}
IrReceiver.resume(); // resume receiver
diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..d3dd74992
--- /dev/null
+++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h
@@ -0,0 +1,366 @@
+/*
+ * 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
+ *
+ * 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)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
+#endif
+
+#if !defined (FLASHEND)
+#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
+#endif
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
+#endif
+#if !defined (RAMSIZE)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
+#endif
diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino
new file mode 100644
index 000000000..7a598f25d
--- /dev/null
+++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino
@@ -0,0 +1,152 @@
+/*
+ * ReceiveAndSendHob2Hood.cpp
+ *
+ * Demonstrates receiving and sending of IR codes for AEG / Elektrolux Hob2Hood protocol
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ ************************************************************************************
+ * MIT License
+ *
+ * Copyright (c) 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
+
+#define DECODE_HASH // Only decoder, which works for Hob2Hood. protocol is UNKNOWN and only raw data is set.
+
+//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
+//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
+//#define NO_LED_FEEDBACK_CODE // Saves 310 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 44 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 34 bytes program memory
+
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+#include
+
+// IR commands from AEG hob2hood device
+#define NUMBER_OF_HOB_TO_HOOD_COMMANDS 7
+#define HOB_TO_HOOD_HASH_CODE_FAN_1 0xE3C01BE2
+#define HOB_TO_HOOD_HASH_CODE_FAN_2 0xD051C301
+#define HOB_TO_HOOD_HASH_CODE_FAN_3 0xC22FFFD7
+#define HOB_TO_HOOD_HASH_CODE_FAN_4 0xB9121B29
+#define HOB_TO_HOOD_HASH_CODE_FAN_OFF 0x55303A3
+#define HOB_TO_HOOD_HASH_CODE_LIGHT_ON 0xE208293C
+#define HOB_TO_HOOD_HASH_CODE_LIGHT_OFF 0x24ACF947
+
+// based on https://pastebin.com/N6kG7Wu5
+#define HOB_TO_HOOD_UNIT_MICROS 725
+#define H2H_1 HOB_TO_HOOD_UNIT_MICROS
+#define H2H_2 (HOB_TO_HOOD_UNIT_MICROS*2) // 1450
+#define H2H_3 (HOB_TO_HOOD_UNIT_MICROS*3) // 2175
+#define H2H_4 (HOB_TO_HOOD_UNIT_MICROS*4) // 2900
+#define H2H_5 (HOB_TO_HOOD_UNIT_MICROS*5) // 3625
+
+// First entry is the length of the raw command
+const uint16_t Fan1[] PROGMEM { 15, H2H_2, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1,
+H2H_3, H2H_1 };
+const uint16_t Fan2[] PROGMEM { 9, H2H_2, H2H_2, H2H_1, H2H_4, H2H_1, H2H_3, H2H_5, H2H_3, H2H_3 };
+const uint16_t Fan3[] PROGMEM { 9, H2H_1, H2H_3, H2H_4, H2H_4, H2H_3, H2H_1, H2H_1, H2H_3, H2H_3 };
+const uint16_t Fan4[] PROGMEM { 13, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_2, H2H_1, H2H_3, H2H_1, H2H_1, H2H_2 };
+const uint16_t FanOff[] PROGMEM { 15, H2H_1, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_2, H2H_3, H2H_1, H2H_2, H2H_1,
+H2H_1, H2H_1 };
+const uint16_t LightOn[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_4, H2H_1,
+H2H_1, H2H_1, H2H_1, H2H_2 };
+const uint16_t LightOff[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_1, H2H_1, H2H_3, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1,
+H2H_2, H2H_1, H2H_1, H2H_1 };
+const uint16_t *const Hob2HoodSendCommands[NUMBER_OF_HOB_TO_HOOD_COMMANDS] = { Fan1, Fan2, Fan3, Fan4, FanOff, LightOn, LightOff }; // Constant array in RAM
+
+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_IRREMOTE));
+
+ // 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);
+
+ Serial.print(F("Ready to receive Hob2Hood IR signals at pin " STR(IR_RECEIVE_PIN)));
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
+ Serial.println(F("Send Hob2Hood IR signals at pin " STR(IR_SEND_PIN)));
+}
+
+/*
+ * Receive and send Hob2Hood protocol
+ */
+void loop() {
+ static long sLastMillisOfSend = 0;
+ static uint8_t sSendCommandIndex = 0;
+
+ if (IrReceiver.decode()) {
+ IrReceiver.resume(); // Early enable receiving of the next IR frame
+ IrReceiver.printIRResultShort(&Serial);
+
+ /*
+ * Finally, check the received data and perform actions according to the received command
+ */
+ switch (IrReceiver.decodedIRData.decodedRawData) {
+ case HOB_TO_HOOD_HASH_CODE_FAN_OFF:
+ Serial.print(F("FAN off"));
+ break;
+ case HOB_TO_HOOD_HASH_CODE_FAN_1:
+ Serial.print(F("FAN 1"));
+ break;
+ case HOB_TO_HOOD_HASH_CODE_FAN_2:
+ Serial.print(F("FAN 2"));
+ break;
+ default:
+ Serial.print(F("unknown Hob2Hood IR command"));
+ break;
+ }
+ }
+
+ /*
+ * Send next command every 5 seconds
+ */
+ if (millis() - sLastMillisOfSend > 2000) {
+ sLastMillisOfSend = millis();
+
+#if defined(__AVR__)
+ uint16_t tLengthOfRawCommand = pgm_read_word(Hob2HoodSendCommands[sSendCommandIndex]); // length is the 1. word in array
+#else
+ uint16_t tLengthOfRawCommand = *Hob2HoodSendCommands[sSendCommandIndex]; // length is the 1. word in array
+#endif
+ const uint16_t *tAddressOfRawCommandSequence = Hob2HoodSendCommands[sSendCommandIndex] + 1; // Raw sequence starts at the 2. word of array
+ Serial.print(F("Send Hob2Hood command index="));
+ Serial.println(sSendCommandIndex);
+ IrSender.sendRaw_P(tAddressOfRawCommandSequence, tLengthOfRawCommand, 38);
+
+ // Prepare for next command
+ sSendCommandIndex++;
+ if (sSendCommandIndex >= NUMBER_OF_HOB_TO_HOOD_COMMANDS) {
+ sSendCommandIndex = 0;
+ }
+ }
+}
diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ReceiveDemo/PinDefinitionsAndMore.h
+++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino
index e2659dec5..6de9fb7f0 100644
--- a/examples/ReceiveDemo/ReceiveDemo.ino
+++ b/examples/ReceiveDemo/ReceiveDemo.ino
@@ -3,14 +3,14 @@
*
* Demonstrates receiving IR codes with the IRremote library and the use of the Arduino tone() function with this library.
* Long press of one IR button (receiving of multiple repeats for one command) is detected.
- * If debug button is pressed (pin connected to ground) a long output is generated.
+ * If debug button is pressed (pin connected to ground) a long output is generated, which may disturb detecting of repeats.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-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
@@ -34,91 +34,133 @@
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
//#define LOCAL_DEBUG // If defined, print timing for each received data set (the same as if DEBUG_BUTTON_PIN was connected to low)
/*
* Specify which protocol(s) should be used for decoding.
- * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
+ * If no protocol is defined, all protocols (except BEO / Bang&Olufsen) are active.
* This must be done before the #include
+ * In alphabetic order
*/
-//#define DECODE_DENON // Includes Sharp
-//#define DECODE_JVC
-//#define DECODE_KASEIKYO
-//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
-//#define DECODE_LG
-//#define DECODE_ONKYO // Decodes only Onkyo and not NEC or Apple
-//#define DECODE_NEC // Includes Apple and Onkyo
-//#define DECODE_SAMSUNG
-//#define DECODE_SONY
-//#define DECODE_RC5
-//#define DECODE_RC6
-
-//#define DECODE_BOSEWAVE
-//#define DECODE_LEGO_PF
-//#define DECODE_MAGIQUEST
-//#define DECODE_WHYNTER
-//#define DECODE_FAST
-
-//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
-//#define DECODE_HASH // special decoder for all protocols
-
-//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
-
-#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+//#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328
+//#define DECODE_JVC // ~ 200 bytes
+//#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes
+//#define DECODE_LG // ~ 400 bytes
+//#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes
+//#define DECODE_SAMSUNG // ~ 300 bytes
+//#define DECODE_SONY // ~ 175 bytes
+//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes
+//#define DECODE_RC6 // ~ 375 bytes
+
+// Universal protocol decoder
+//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes
+//#define DECODE_HASH // special decoder for all protocols ~ 250 bytes
+
+// Exotic protocol decoder
+//#define DECODE_BOSEWAVE // ~ 140 bytes
+//#define DECODE_FAST // ~ 135 bytes
+//#define DECODE_LEGO_PF // ~ 300 bytes
+//#define DECODE_MAGIQUEST // ~ 270 bytes
+//#define DECODE_MARANTZ // RC5 + MARANTZ: ~ 425 bytes
+//#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command. ~ 175 bytes
+//#define DECODE_WHYNTER // ~ 90 bytes
+
+//#define DECODE_ONKYO // Decodes NEC and Apple as Onkyo - saves around 90 bytes of program memory, if activated
+//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY! ~ 430 bytes
+#if FLASHEND >= 0x7FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+// Do not enable any protocol explicitly => all protocols are enabled automatically.
// !!! Enabling B&O disables detection of Sony, because the repeat gap for SONY is smaller than the B&O frame gap :-( !!!
-//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY!
-#endif
-#if defined(DECODE_BEO)
-#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer, but this prevents decoding of SONY!
+//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY! ~ 430 bytes
+#else
+// for 8k flash
+//#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328
+//#define DECODE_JVC // ~ 200 bytes
+#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes
+#define DECODE_LG // ~ 400 bytes
+#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes
+#define DECODE_SAMSUNG // ~ 300 bytes
+//#define DECODE_SONY // ~ 175 bytes
+//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes
+//#define DECODE_RC6 // ~ 375 bytes
+#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes
+#define DECODE_HASH // special decoder for all protocols ~ 250 bytes
+
+#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 90 bytes of program memory, if activated
#endif
// etc. see IRremote.hpp
//
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 130 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
-#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# else
-#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
+# elif RAMSIZE <= 0x800
+// Here we have 2 k RAM or less, otherwise use default of 750
+#define RAW_BUFFER_LENGTH 600 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten.
# endif
#endif
-//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
+//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
-//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 1 bytes program memory.
+//#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory
+//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us
+#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints the reason which prevents data to be decoded as distance width data
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
+#if defined(DECODE_BEO)
+#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer, but this prevents decoding of SONY!
+#endif
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include
-#if defined(APPLICATION_PIN)
-#define DEBUG_BUTTON_PIN APPLICATION_PIN // if low, print timing for each received data set
+#if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN)
+#define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data
#else
#define DEBUG_BUTTON_PIN 6
#endif
+#if defined(ESP32) && defined(DEBUG_BUTTON_PIN)
+# if !digitalPinIsValid(DEBUG_BUTTON_PIN)
+#undef DEBUG_BUTTON_PIN // DEBUG_BUTTON_PIN number is not valid, so delete definition to disable further usage
+# endif
+#endif
+
+/*
+ * Using the function printActiveIRProtocols() requires additional 314 bytes program memory
+ * Using the function printIRResultShort() requires additional 1450 bytes program memory
+ * Using the function printIRSendUsage() requires additional 2736 bytes program memory
+ * Because these 3 functions all share common code, using all 3 functions requires only additional 3016 bytes program memory
+ */
+void generateTone();
+void handleOverflow();
bool detectLongPress(uint16_t aLongPressDurationMillis);
void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+# if defined(DEBUG_BUTTON_PIN)
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
+# endif
#endif
Serial.begin(115200);
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
+
+#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(ESP32) && defined(ARDUINO_USB_MODE))
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_IRREMOTE));
@@ -137,23 +179,33 @@ void setup() {
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#endif
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
Serial.println();
+# if defined(DEBUG_BUTTON_PIN)
Serial.print(F("If you connect debug pin "));
-# if defined(APPLICATION_PIN_STRING)
- Serial.print(APPLICATION_PIN_STRING);
-# else
Serial.print(DEBUG_BUTTON_PIN);
+ Serial.println(F(" to ground, raw data is always printed and tone is disabled"));
# endif
- Serial.println(F(" to ground, raw data is always printed"));
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
-#endif
-
+# endif
+#endif // FLASHEND >= 0x3FFF
}
void loop() {
@@ -164,114 +216,95 @@ void loop() {
* E.g. command is in IrReceiver.decodedIRData.command
* address is in command is in IrReceiver.decodedIRData.address
* and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
- *
- * At 115200 baud, printing takes 40 ms for NEC protocol and 10 ms for NEC repeat
*/
if (IrReceiver.decode()) {
Serial.println();
-#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
+#if FLASHEND < 0x3FFF // For less than 16k flash, only print a minimal summary of received data
+ IrReceiver.printIRResultMinimal(&Serial);
+#else
+
+ /*
+ *
+ */
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
- Serial.println(F("Overflow detected"));
- Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
- // see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
-# if !defined(ESP8266) && !defined(NRF5)
+ handleOverflow();
+ } else {
/*
- * do double beep
+ * No overflow here.
+ * Stop receiver, generate a single beep, print short info and send usage and start receiver again
*/
-# if !defined(ESP32)
- IrReceiver.stop(); // ESP32 uses another timer for tone()
-# endif
- tone(TONE_PIN, 1100, 10);
- delay(50);
- tone(TONE_PIN, 1100, 10);
- delay(50);
-# if !defined(ESP32)
- IrReceiver.start(100000); // to compensate for 100 ms stop of receiver. This enables a correct gap measurement.
-# endif
-# endif
-
- } else {
- auto tStartMillis = millis();
-# if !defined(ESP32)
- IrReceiver.stop(); // ESP32 uses another timer for tone()
-# endif
- tone(TONE_PIN, 2200);
-
- // No overflow, print a short summary of received data
-# if defined(LOCAL_DEBUG)
- IrReceiver.printIRResultShort(&Serial, true);
-# else
- IrReceiver.printIRResultShort(&Serial, true, digitalRead(DEBUG_BUTTON_PIN) == LOW);
-# endif
- // Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
- // so here we are 10 millis after end of frame. Sony20 has only a 12 ms repeat gap.
- while ((millis() - tStartMillis) < 5)
- ;
- noTone(TONE_PIN);
-
-# if !defined(ESP32)
- // Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
- IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
-# endif
+ if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH)
+ && (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN)
+#if defined(DEBUG_BUTTON_PIN)
+ && digitalRead(DEBUG_BUTTON_PIN) != LOW
+#endif
+ ) {
+ /*
+ * For SONY the tone prevents the detection of a repeat after the 15 ms SONY gap.
+ * In debug mode and for unknown protocols, we need the time for extended output.
+ * Skipping tone will get exact gap time between transmissions and not running into repeat frames while wait for tone to end.
+ * This in turn enables the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value.
+ */
+ generateTone();
+ }
- IrReceiver.printIRSendUsage(&Serial);
-# if defined(LOCAL_DEBUG)
- IrReceiver.printIRResultRawFormatted(&Serial, true);
-# else
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
- // We have an unknown protocol, print more info
+ /*
+ * Print info
+ */
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+#if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+#endif
+ ) {
+ // We have debug enabled or an unknown protocol, print extended info
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
}
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
-# endif
- }
-
- // tone on esp8266 works once, then it disables the successful IrReceiver.start() / timerConfigForReceive().
-# if !defined(ESP8266) && !defined(NRF5) && !defined(LOCAL_DEBUG)
- if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH)
- && (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN)
- && digitalRead(DEBUG_BUTTON_PIN) != LOW) {
- /*
- * If no debug mode or a valid protocol was received, play tone, wait and restore IR timer.
- * For SONY the tone prevents the detection of a repeat
- * Otherwise do not play a tone to get exact gap time between transmissions and not running into repeat frames while wait for tone to end.
- * This will give the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value.
- */
-# if !defined(ESP32)
- IrReceiver.stop(); // ESP32 uses another timer for tone()
-# endif
- tone(TONE_PIN, 2200, 8);
-# if !defined(ESP32)
- delay(8);
- IrReceiver.start(8000); // Restore IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
+ auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs
+ Serial.print(F("Raw data from hash decoder is 0x"));
+# if (__INT_WIDTH__ < 32)
+ Serial.println(tDecodedRawData);
+# else
+ PrintULL::println(&Serial, tDecodedRawData, BIN);
# endif
+
+ } else {
+ /*
+ * The info output for a successful receive
+ */
+ IrReceiver.printIRResultShort(&Serial);
+ IrReceiver.printIRSendUsage(&Serial); // Calls printIRResultShort() and other functions, if protocol is UNKNOWN
+ }
}
-# endif
-#else // #if FLASHEND >= 0x3FFF
- // Print a minimal summary of received data
- IrReceiver.printIRResultMinimal(&Serial);
#endif // #if FLASHEND >= 0x3FFF
/*
- * !!!Important!!! Enable receiving of the next value,
- * since receiving has stopped after the end of the current received data packet.
+ * !!!Important!!! Enable receiving of the next value, because receiving
+ * has stopped after the end of the current received data packet.
+ * Do it here, to preserve raw data for printing with printIRResultRawFormatted()
*/
IrReceiver.resume();
/*
* Finally check the received data and perform actions according to the received address and commands
*/
- if (IrReceiver.decodedIRData.address == 0) {
- if (IrReceiver.decodedIRData.command == 0x10) {
- // do something
- } else if (IrReceiver.decodedIRData.command == 0x11) {
- // do something else
+
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (IrReceiver.decodedIRData.address == 0) {
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ // do something else
+ }
}
}
- // Check if the command was repeated for more than 1000 ms
+ // Check if repeats of the IR command was sent for more than 1000 ms
if (detectLongPress(1000)) {
Serial.print(F("Command 0x"));
Serial.print(IrReceiver.decodedIRData.command, HEX);
@@ -289,10 +322,54 @@ void loop() {
}
+#if FLASHEND >= 0x3FFF // No tone() available when using ATTinyCore
+/*
+ * Stop receiver, generate a single beep and start receiver again
+ */
+void generateTone() {
+# if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
+# if defined(ESP32) // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too.
+ tone(TONE_PIN, 2200, 8);
+# else
+ IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
+ tone(TONE_PIN, 2200, 8);
+ delay(8);
+ IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
+# endif
+# endif
+}
+#endif // FLASHEND >= 0x3FFF
+
+void handleOverflow() {
+ Serial.println(F("Overflow detected"));
+ Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
+ // see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
+
+#if !defined(ESP8266) && !defined(NRF5) && FLASHEND >= 0x3FFF && defined(TONE_PIN) // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
+ /*
+ * Stop timer, generate a double beep and start timer again
+ */
+# if defined(ESP32) // ESP32 uses another timer for tone()
+ tone(TONE_PIN, 1100, 10);
+ delay(50);
+ tone(TONE_PIN, 1100, 10);
+# else
+ IrReceiver.stopTimer();
+ tone(TONE_PIN, 1100, 10);
+ delay(50);
+ tone(TONE_PIN, 1100, 10);
+ delay(50);
+ IrReceiver.restartTimer();
+# endif
+#endif
+}
+
unsigned long sMillisOfFirstReceive;
bool sLongPressJustDetected;
/**
- * @return true once after the repeated command was received for longer than aLongPressDurationMillis milliseconds, false otherwise.
+ * True once we received the consecutive repeats for more than aLongPressDurationMillis milliseconds.
+ * The first frame, which is no repeat, is NOT counted for the duration!
+ * @return true once after the repeated IR command was received for longer than aLongPressDurationMillis milliseconds, false otherwise.
*/
bool detectLongPress(uint16_t aLongPressDurationMillis) {
if (!sLongPressJustDetected && (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {
diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ReceiveDump/PinDefinitionsAndMore.h
+++ b/examples/ReceiveDump/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino
index 0f3297788..84b570061 100644
--- a/examples/ReceiveDump/ReceiveDump.ino
+++ b/examples/ReceiveDump/ReceiveDump.ino
@@ -10,7 +10,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2022 Armin Joachimsmeyer
+ * Copyright (c) 2020-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
@@ -33,32 +33,32 @@
*/
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
-
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
# else
-#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Here we most likely have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 750 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000
# endif
#endif
/*
* MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
- * to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
+ * to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+ * 20 is taken as default if not otherwise specified / defined.
*
* You can change this value accordingly to the receiver module you use.
* The required value can be derived from the timings printed here.
* Keep in mind that the timings may change with the distance
* between sender and receiver as well as with the ambient light intensity.
*/
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
-
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
+//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
//+=============================================================================
@@ -68,9 +68,17 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200); // Status message will be sent to PC at 9600 baud
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || 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!
+
+#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_IRREMOTE));
@@ -84,10 +92,22 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
+ Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
+
+ Serial.println();
+ Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!"));
Serial.println();
- Serial.println(F("Because of the verbose output (>200 ms at 115200), repeats are probably not dumped correctly!"));
+ Serial.println(
+ F(
+ "If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2 or SamsungLG, which is determined by the repeats"));
Serial.println();
+
}
//+=============================================================================
@@ -118,10 +138,14 @@ void loop() {
Serial.print(F("Result as internal 8bit ticks (50 us) array - compensated with MARK_EXCESS_MICROS="));
Serial.println(MARK_EXCESS_MICROS);
IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, false); // Output the results as uint8_t source code array of ticks
+ Serial.println(); // blank line between entries
Serial.print(F("Result as microseconds array - compensated with MARK_EXCESS_MICROS="));
Serial.println(MARK_EXCESS_MICROS);
IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros
+ Serial.println(); // blank line between entries
IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables
+ Serial.println(); // blank line between entries
+ Serial.println(); // blank line between entries
IrReceiver.compensateAndPrintIRResultAsPronto(&Serial);
@@ -129,7 +153,7 @@ void loop() {
* Example for using the compensateAndStorePronto() function.
* Creating this String requires 2210 bytes program memory and 10 bytes RAM for the String class.
* The String object itself requires additional 440 bytes RAM from the heap.
- * This values are for an Arduino UNO.
+ * This values are for an Arduino Uno.
*/
// Serial.println(); // blank line between entries
// String ProntoHEX = F("Pronto HEX contains: "); // Assign string to ProtoHex string object
@@ -144,6 +168,6 @@ void loop() {
// Serial.println(); // blank line between entries
// }
}
- IrReceiver.resume(); // Prepare for the next value
+ IrReceiver.resume(); // Prepare for the next IR frame
}
}
diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
+++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
index 34baa144e..f7277fa6b 100644
--- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
+++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
@@ -13,7 +13,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2022 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 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
@@ -44,7 +44,7 @@
// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED
// GND 4| |5 PB0 (0) IR Input
// +----+
-/* SAUMSUMG REMOTE CODES (Model: BN59-01180A)
+/* SAUMSUMG REMOTE CODES (Model: BN59-01180A) - Address is 0x07
* Power Button - 0x2
* Power Off - 0x98
* 1 - 0x4
@@ -90,11 +90,13 @@
#include
+//#define NO_LED_FEEDBACK_CODE // Saves 104 bytes program memory
+
// select only Samsung protocol for sending and receiving
#define DECODE_SAMSUNG
-#define ADDRESS_OF_SAMSUNG_REMOTE 0x0707 // The value you see as address in printIRResultShort()
+#define ADDRESS_OF_SAMSUNG_REMOTE 0x07 // The value you see as address in printIRResultShort()
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
void sendSamsungSmartHubMacro(bool aDoSelect);
@@ -104,14 +106,18 @@ 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_attiny3217)
+
+#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_IRREMOTE));
// tone before IR setup, since it kills the IR timer settings
+#if defined(TONE_PIN)
tone(TONE_PIN, 2200, 400);
+#endif
digitalWrite(LED_BUILTIN, HIGH);
delay(400);
digitalWrite(LED_BUILTIN, LOW);
@@ -123,7 +129,11 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
}
@@ -189,9 +199,9 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS;
}
-# if !defined(ESP32)
- IrReceiver.stop(); // ESP32 uses another timer for tone()
-# endif
+#if !defined(ESP32) // ESP32 uses another timer for tone(), so the receiver must not be stopped and restarted for it
+ IrReceiver.stopTimer();
+#endif
if (millis() < tWaitTimeAfterBoot) {
// division by 1000 and printing requires much (8%) program memory
Serial.print(F("It is "));
@@ -200,10 +210,12 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
Serial.print(tWaitTimeAfterBoot / 1000);
Serial.println(F(" seconds after boot to be ready for the command"));
+#if defined(TONE_PIN)
tone(TONE_PIN, 2200, 100);
delay(200);
tone(TONE_PIN, 2200, 100);
delay(100);
+#endif
if (millis() < tWaitTimeAfterBoot) {
Serial.print(F("Now do a blocking wait for "));
@@ -214,12 +226,14 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
}
// Do beep feedback for special key to be received
+#if defined(TONE_PIN)
tone(TONE_PIN, 2200, 200);
delay(200);
+#endif
-# if !defined(ESP32)
- IrReceiver.start(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement.
-# endif
+#if !defined(ESP32)
+ IrReceiver.restartTimer(); // Restart IR timer.
+#endif
Serial.println(F("Wait for \"not supported\" to disappear"));
delay(2000);
diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
index 1ee2bf92b..99e67014e 100644
--- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
+++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
@@ -11,7 +11,6 @@
*
*
* 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.
@@ -33,48 +32,59 @@
#include
-#define IR_INPUT_PIN 2
-//#define IR_INPUT_PIN 3
+#define IR_RECEIVE_PIN 2
+//#define IR_RECEIVE_PIN 3
-/*
- * Helper macro for getting a macro definition as string
- */
+// 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()
-{
+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_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!
+#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_INPUT_PIN == 2)
+# 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_INPUT_PIN == 3)
+# 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
- attachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN), measureTimingISR, CHANGE);
+# 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_INPUT_PIN)));
+ 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
-{
+struct timingStruct {
uint16_t minimum;
uint8_t indexOfMinimum;
uint16_t maximum;
@@ -93,23 +103,19 @@ struct timingStruct LongSpace;
/*
* Compute minimum, maximum and average
*/
-void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue)
-{
- if (aTimingStruct->SampleCount == 0)
- {
+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)
- {
+ if (aTimingStruct->minimum > aValue) {
aTimingStruct->minimum = aValue;
aTimingStruct->indexOfMinimum = aTimingStruct->SampleCount;
}
- if (aTimingStruct->maximum < aValue)
- {
+ if (aTimingStruct->maximum < aValue) {
aTimingStruct->maximum = aValue;
aTimingStruct->indexOfMaximum = aTimingStruct->SampleCount;
}
@@ -120,8 +126,7 @@ void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue)
}
-void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption)
-{
+void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) {
// if (aTimingStruct->LastPrintedCount != aTimingStruct->SampleCount)
// {
// aTimingStruct->LastPrintedCount = aTimingStruct->SampleCount;
@@ -145,10 +150,8 @@ void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption)
// }
}
-void loop()
-{
- if (Mark.SampleCount >= 32)
- {
+void loop() {
+ if (Mark.SampleCount >= 32) {
/*
* This check enables statistics for longer protocols like Kaseikyo/Panasonics
*/
@@ -161,8 +164,7 @@ void loop()
#endif
uint32_t tMicrosDelta = micros() - tLastMicros;
- if (tMicrosDelta > 10000)
- {
+ if (tMicrosDelta > 10000) {
// NEC signal ended just now
Serial.println();
printTimingValues(&Mark, "Mark ");
@@ -197,9 +199,9 @@ void loop()
void IRAM_ATTR measureTimingISR()
#else
# if defined(EICRA) && defined(EIFR) && defined(EIMSK)
-# if (IR_INPUT_PIN == 2)
+# if (IR_RECEIVE_PIN == 2)
ISR(INT0_vect)
-# elif (IR_INPUT_PIN == 3)
+# elif (IR_RECEIVE_PIN == 3)
ISR(INT1_vect)
# endif
# else
@@ -213,44 +215,34 @@ void measureTimingISR()
/*
* read level and give feedback
*/
- uint8_t tInputLevel = digitalRead(IR_INPUT_PIN);
+ uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN);
digitalWrite(LED_BUILTIN, !tInputLevel);
- if (tMicrosDelta > 10000)
- {
+ 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
- {
+ } else {
ISREdgeCounter++;
}
/*
* Skip header mark and space and first bit mark and space
*/
- if (ISREdgeCounter > 4)
- {
- if (tInputLevel != LOW)
- {
+ if (ISREdgeCounter > 4) {
+ if (tInputLevel != LOW) {
// Mark ended
processTmingValue(&Mark, tMicrosDelta);
// Serial.print('M');
- }
- else
- {
+ } else {
// Space ended
- if (tMicrosDelta > 1000)
- {
+ if (tMicrosDelta > 1000) {
// long space - logical 1
processTmingValue(&LongSpace, tMicrosDelta);
Serial.print('1');
- }
- else
- {
+ } else {
// short space - logical 0
processTmingValue(&ShortSpace, tMicrosDelta);
Serial.print('0');
diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendAndReceive/PinDefinitionsAndMore.h
+++ b/examples/SendAndReceive/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino
index 7303c1afc..7aaabf8c5 100644
--- a/examples/SendAndReceive/SendAndReceive.ino
+++ b/examples/SendAndReceive/SendAndReceive.ino
@@ -38,14 +38,17 @@
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
-//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
-//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // saves 318 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 44 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 36 bytes program memory
+//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
#define DELAY_AFTER_SEND 2000
@@ -53,7 +56,9 @@
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_attiny3217)
+
+#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
@@ -65,7 +70,11 @@ void setup() {
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
@@ -87,8 +96,13 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
}
diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
+++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
index 054c083c1..d6b44faa3 100644
--- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
+++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
@@ -33,9 +33,13 @@
*/
#include
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+
+//#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
//......................................................................
@@ -96,6 +100,10 @@
//#define BOSE_CMD_ALARM_ON_OFF 0x22
//#define BOSE_CMD_ALARM_WAKE_TO 0x70
//#define BOSE_CMD_ALARM_TIME 0x23
+// Different last 3 codes for Wave Sound Touch IV
+//#define BOSE_CMD_ALARM_1 0x22
+//#define BOSE_CMD_ALARM_2 0x62
+//#define BOSE_CMD_ALARM_SETUP 0xA2
bool sPrintMenu;
void printMenu();
@@ -104,18 +112,28 @@ 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_attiny3217)
+
+#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_IRREMOTE));
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#else
- IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
- Serial.println(F("Send IR signals at pin 3"));
+ uint8_t tSendPin = 3;
+ IrSender.begin(tSendPin); // Specify send pin and enable feedback LED at default feedback LED pin
+ // You can change send pin later with IrSender.setSendPin();
+
+ Serial.print(F("Send IR signals at pin "));
+ Serial.println(tSendPin);
#endif
sPrintMenu = true;
diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendDemo/PinDefinitionsAndMore.h
+++ b/examples/SendDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino
index 97e7fa29a..d11622003 100644
--- a/examples/SendDemo/SendDemo.ino
+++ b/examples/SendDemo/SendDemo.ino
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-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
@@ -32,40 +32,80 @@
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
-
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
-
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+//#define IR_USE_AVR_TIMER1
//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
+//#define USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin.
+//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-//#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory
-//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
+//#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal.
+//#define NO_LED_FEEDBACK_CODE // Saves 322 bytes program memory
+
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+#if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85
+#define NO_LED_FEEDBACK_CODE
+#endif
+//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
#include
#define DELAY_AFTER_SEND 2000
#define DELAY_AFTER_LOOP 5000
+#if __INT_WIDTH__ < 32
+IRDecodedRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
+/*
+ * Alternative definition of tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010}
+ * But be aware, that this requires a cast when using tRawDataPGM as parameter.
+ * Like sendPulseDistanceWidthFromPGMArray_P(..., (IRDecodedRawDataType*) &tRawDataPGM[0], ...);
+ */
+//uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/
+//0x10, 0xA0, 0x0, 0x0, /*0xA010*/};
+#endif
+
+const uint16_t rawIRTimingsNEC[]
+#if defined(__AVR__)
+PROGMEM // this crashes on ESP8266
+#endif
+= { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560,
+ 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560,
+ 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560,
+ 560/*0000 0x00*/, 560, 1690, 560, 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690,
+ 560, 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
+
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_attiny3217)
+#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_IRREMOTE));
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
# if defined(IR_SEND_PIN_STRING)
Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
# endif
#else
- IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
- Serial.println(F("Send IR signals at pin 3"));
+ // Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN
+ uint8_t tSendPin = 3;
+ IrSender.begin(tSendPin); // Specify send pin and use feedback LED at default feedback LED pin
+ // You can change send pin later with IrSender.setSendPin();
+
+ Serial.print(F("Send IR signals at pin "));
+ Serial.println(tSendPin);
#endif
#if !defined(SEND_PWM_BY_TIMER)
@@ -81,16 +121,27 @@ void setup() {
Serial.print(IrSender.periodTimeMicros);
Serial.println(F(" us"));
#endif
+
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE) && !defined(NO_LED_SEND_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
}
/*
* Set up the data to be sent.
* For most protocols, the data is build up with a constant 8 (or 16 byte) address
* and a variable 8 bit command.
- * There are exceptions like Sony and Denon, which have 5 bit address.
+ * There are exceptions like Sony, Denon or Marantz, which have 5 bit address.
+ * Furthermore, the extended protocol from Marantz has a 6 bit command extension.
*/
uint16_t sAddress = 0x0102;
uint8_t sCommand = 0x34;
+uint8_t sCommandExtension = 0x0B; // Only used for Marantz extended protocol
uint16_t s16BitCommand = 0x5634;
uint8_t sRepeats = 0;
@@ -125,11 +176,23 @@ void loop() {
delay(DELAY_AFTER_SEND);
if (sRepeats == 0) {
-#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+#if FLASHEND >= 0x3FFF && RAMSIZE >= 0x600
/*
+ * For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
* Send constant values only once in this demo
*/
- Serial.println(F("Sending NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
+
+ /*
+ * Test send usage for UNKNOWN protocol
+ */
+ const uint16_t rawIRTimings[] = { 9000, 4500/*Start bit*/, 500, 1000, 1000, 500, 500, 2000, 2000, 500, 500, 3000, 3000, 500,
+ 500, 250, 250, 500 };
+ Serial.println(F("Send arbitrary raw data with exact timing (16 bit array format) with sendRaw()"));
+ Serial.flush();
+ IrSender.sendRaw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), NEC_KHZ, 80, 1); // Note the approach used to automatically calculate the size of the array.
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()"));
Serial.flush();
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
"0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */
@@ -140,18 +203,13 @@ void loop() {
delay(DELAY_AFTER_SEND);
/*
- * !!! The next data occupies 136 bytes RAM !!!
+ * Test sending NEC protocol using sendRaw_P
*/
Serial.println(
- F("Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)"));
+ F(
+ "Send NEC data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format) with sendRaw_P()"));
Serial.flush();
- const uint16_t irSignal[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
- 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690,
- 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560,
- 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560,
- 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560,
- 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
- IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
+ IrSender.sendRaw_P(rawIRTimingsNEC, sizeof(rawIRTimingsNEC) / sizeof(rawIRTimingsNEC[0]), NEC_KHZ, 110, 1); // Note the approach used to automatically calculate the size of the array.
delay(DELAY_AFTER_SEND);
/*
@@ -165,6 +223,7 @@ void loop() {
/*
* With Send sendNECMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte.
+ * Use bitreverse32Bit().
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
@@ -172,74 +231,100 @@ void loop() {
Serial.flush();
IrSender.sendNECMSB(0x40802CD3, 32, false);
delay(DELAY_AFTER_SEND);
-#endif
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432"));
Serial.flush();
-#if __INT_WIDTH__ < 32
- IRRawDataType tRawData[] = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
-#else
- IrSender.sendPulseDistanceWidth(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
-#endif
+# if __INT_WIDTH__ < 32
+ IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48,
+ NO_REPEATS); // Panasonic is a Kaseikyo variant
+# else
+ IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+# endif
delay(DELAY_AFTER_SEND);
/*
- * Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first
+ * Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first
*/
- Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400"));
Serial.println(F(" LSB first"));
Serial.flush();
-#if __INT_WIDTH__ < 32
- IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
+# if __INT_WIDTH__ < 32
+ IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRDecodedRawDataType*) tRawDataPGM, 48,
PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
-#else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
- 0, NO_REPEATS);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
// The same with MSB first. Use bit reversed raw data of LSB first part
Serial.println(F(" MSB first"));
-#if __INT_WIDTH__ < 32
+ IRDecodedRawDataType tRawData[4];
+# if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
-#else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST,
- 0, NO_REPEATS);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600"));
Serial.flush();
-# if __INT_WIDTH__ < 32
+# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
tRawData[1] = 0xAFEDCBA9;
tRawData[2] = 0x5A;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
NO_REPEATS);
-# else
- IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
-# endif
+# else
+ tRawData[0] = 0xAFEDCBA987654321;
+ tRawData[1] = 0x5A; // LSB of tRawData[0] is sent first
+ IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
-#if __INT_WIDTH__ < 32
+# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52,
PROTOCOL_IS_LSB_FIRST, 0, 0);
-#else
- IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
- 0, 0);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# endif
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(
+ F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600"));
+ Serial.flush();
+# if __INT_WIDTH__ < 32
+ tRawData[2] = ~tRawData[0];
+ tRawData[3] = ~tRawData[1];
+ IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# else
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# endif
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500"));
+ Serial.flush();
+ // Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
+ IrSender.sendPulseDistanceWidth(38, 6000, 500, 500, 1500, 1500, 500, sCommand, 7, PROTOCOL_IS_LSB_FIRST, 0, 0);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first"));
+ Serial.println(F("Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600"));
+ Serial.flush();
+ uint32_t tData = (uint32_t) sAddress << 7 | (sCommand & 0x7F);
+ IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, tData, SIRCS_12_PROTOCOL, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ delay(DELAY_AFTER_SEND);
+#endif // FLASHEND >= 0x3FFF ...
+
+ Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
@@ -296,14 +381,19 @@ void loop() {
IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Samsung 8 bit command"));
+ Serial.println(F("Send Samsung 8 bit command and 8 bit address"));
Serial.flush();
- IrSender.sendSamsung(sAddress, sCommand, sRepeats);
+ IrSender.sendSamsung(sAddress & 0xFF, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Samsung 16 bit command"));
+ Serial.println(F("Send Samsung 8 bit command and 16 bit address"));
Serial.flush();
- IrSender.sendSamsung(sAddress, s16BitCommand, sRepeats);
+ IrSender.sendSamsung16BitAddressAnd8BitCommand(sAddress, sCommand, sRepeats);
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send Samsung 16 bit command and address"));
+ Serial.flush();
+ IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Samsung48 16 bit command"));
@@ -321,12 +411,44 @@ void loop() {
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
delay(DELAY_AFTER_SEND);
+ Serial.println(F("Send Marantz variant of RC5x with 6 command bits and additional command extension"));
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sRepeats, sCommandExtension);
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send Marantz variant of RC5x with 7 command bits and additional command extension"));
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sRepeats, sCommandExtension);
+ delay(DELAY_AFTER_SEND);
+
Serial.println(F("Send RC6"));
Serial.flush();
IrSender.sendRC6(sAddress, sCommand, sRepeats, true);
delay(DELAY_AFTER_SEND);
-#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+ Serial.println(F("Send RC6A with 14 bit 0x2711 as extra"));
+ Serial.flush();
+ IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true);
+ delay(DELAY_AFTER_SEND);
+
+#if FLASHEND >= 0x3FFF && RAMSIZE >= 0x400 // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+
+ Serial.println(F("Send MagiQuest"));
+ Serial.flush();
+ IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send OpenLASIR"));
+ Serial.flush();
+ IrSender.sendOpenLASIR(sAddress & 0xFF, sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE, sRepeats);
+ delay(DELAY_AFTER_SEND);
+
+ // Bang&Olufsen must be sent with 455 kHz
+// Serial.println(F("Send Bang&Olufsen"));
+// Serial.flush();
+// IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats);
+// delay(DELAY_AFTER_SEND);
+
/*
* Next example how to use the IrSender.write function
*/
@@ -336,12 +458,8 @@ void loop() {
IRSendData.command = sCommand;
IRSendData.flags = IRDATA_FLAGS_EMPTY;
- IRSendData.protocol = SAMSUNG;
- Serial.print(F("Send "));
- Serial.println(getProtocolString(IRSendData.protocol));
+ Serial.println(F("Send next protocols with IrSender.write"));
Serial.flush();
- IrSender.write(&IRSendData, sRepeats);
- delay(DELAY_AFTER_SEND);
IRSendData.protocol = JVC; // switch protocol
Serial.print(F("Send "));
@@ -350,7 +468,7 @@ void loop() {
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
- IRSendData.command = s16BitCommand; // LG support more than 8 bit command
+ IRSendData.command = s16BitCommand; // LG support more than 8 bit command
IRSendData.protocol = SAMSUNG;
Serial.print(F("Send "));
@@ -366,17 +484,6 @@ void loop() {
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send MagiQuest"));
- Serial.flush();
- IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address
- delay(DELAY_AFTER_SEND);
-
- // Bang&Olufsen must be sent with 455 kHz
-// Serial.println(F("Send Bang&Olufsen"));
-// Serial.flush();
-// IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats);
-// delay(DELAY_AFTER_SEND);
-
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
Serial.flush();
diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
+++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendLGAirConditionerDemo/Readme.md b/examples/SendLGAirConditionerDemo/Readme.md
deleted file mode 100644
index ad16367c0..000000000
--- a/examples/SendLGAirConditionerDemo/Readme.md
+++ /dev/null
@@ -1,93 +0,0 @@
-=== decoding for LG A/C ====
-- 1) remote of LG AC has two type of HDR mark/space, 8000/4000 and 3100/10000
-- 2) HDR 8000/4000 is decoded using decodeLG(IRrecvDumpV2) without problem
-- 3) for HDR 3100/10000, use AnalysIR's code : http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/
-- 4) for bin output based on AnalysIR's code : https://gist.github.com/chaeplin/a3a4b4b6b887c663bfe8
-- 5) remove first two byte(11)
-- 6) sample rawcode with bin output : https://gist.github.com/chaeplin/134d232e0b8cfb898860
-
-
-=== *** ===
-- 1) Sample raw code : https://gist.github.com/chaeplin/ab2a7ad1533c41260f0d
-- 2) send raw code : https://gist.github.com/chaeplin/7c800d3166463bb51be4
-
-
-=== *** ===
-- (0) : Cooling or Heating
-- (1) : fixed address
-- (2) : fixed address
-- (3) : special(power, swing, air clean)
-- (4) : change air flow, temperature, cooling(0)/heating(4)
-- (5) : temperature ( 15 + (5) = )
-- (6) : air flow
-- (7) : checksum ( 3 + 4 + 5 + 6 ) & B00001111
-
-
-°F = °C × 1.8 + 32
-°C = (°F - 32) / 1.8
-
-
-=== *** ===
-* remote / Korea / without heating
-
-| status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7)
-|----------------|---|----|----|----|----|----|----|----
-| on / 25 / mid | C |1000|1000|0000|0000|1010|0010|1100
-| on / 26 / mid | C |1000|1000|0000|0000|1011|0010|1101
-| on / 27 / mid | C |1000|1000|0000|0000|1100|0010|1110
-| on / 28 / mid | C |1000|1000|0000|0000|1101|0010|1111
-| on / 25 / high | C |1000|1000|0000|0000|1010|0100|1110
-| on / 26 / high | C |1000|1000|0000|0000|1011|0100|1111
-| on / 27 / high | C |1000|1000|0000|0000|1100|0100|0000
-| on / 28 / high | C |1000|1000|0000|0000|1101|0100|0001
-|----------------|---|----|----|----|----|----|----|----
-| 1 up | C |1000|1000|0000|1000|1101|0100|1001
-|----------------|---|----|----|----|----|----|----|----
-| Cool power | C |1000|1000|0001|0000|0000|1100|1101
-| energy saving | C |1000|1000|0001|0000|0000|0100|0101
-| power | C |1000|1000|0001|0000|0000|1000|1001
-| flow/up/down | C |1000|1000|0001|0011|0001|0100|1001
-| up/down off | C |1000|1000|0001|0011|0001|0101|1010
-| flow/left/right| C |1000|1000|0001|0011|0001|0110|1011
-| left/right off | C |1000|1000|0001|0011|0001|0111|1100
-|----------------|---|----|----|----|----|----|----|----
-| Air clean | C |1000|1000|1100|0000|0000|0000|1100
-|----------------|---|----|----|----|----|----|----|----
-| off | C |1000|1000|1100|0000|0000|0101|0001
-
-
-
-* remote / with heating
-* converted using raw code at https://github.com/chaeplin/RaspAC/blob/master/lircd.conf
-
-| status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7)
-|----------------|---|----|----|----|----|----|----|----
-| on | C |1000|1000|0000|0000|1011|0010|1101
-|----------------|---|----|----|----|----|----|----|----
-| off | C |1000|1000|1100|0000|0000|0101|0001
-|----------------|---|----|----|----|----|----|----|----
-| 64 / 18 | C |1000|1000|0000|0000|0011|0100|0111
-| 66 / 19 | C |1000|1000|0000|0000|0100|0100|1000
-| 68 / 20 | C |1000|1000|0000|0000|0101|0100|1001
-| 70 / 21 | C |1000|1000|0000|0000|0110|0100|1010
-| 72 / 22 | C |1000|1000|0000|0000|0111|0100|1011
-| 74 / 23 | C |1000|1000|0000|0000|1000|0100|1100
-| 76 / 25 | C |1000|1000|0000|0000|1010|0100|1110
-| 78 / 26 | C |1000|1000|0000|0000|1011|0100|1111
-| 80 / 27 | C |1000|1000|0000|0000|1100|0100|0000
-| 82 / 28 | C |1000|1000|0000|0000|1101|0100|0001
-| 84 / 29 | C |1000|1000|0000|0000|1110|0100|0010
-| 86 / 30 | C |1000|1000|0000|0000|1111|0100|0011
-|----------------|---|----|----|----|----|----|----|----
-| heat64 | H |1000|1000|0000|0100|0011|0100|1011
-| heat66 | H |1000|1000|0000|0100|0100|0100|1100
-| heat68 | H |1000|1000|0000|0100|0101|0100|1101
-| heat70 | H |1000|1000|0000|0100|0110|0100|1110
-| heat72 | H |1000|1000|0000|0100|0111|0100|1111
-| heat74 | H |1000|1000|0000|0100|1000|0100|0000
-| heat76 | H |1000|1000|0000|0100|1001|0100|0001
-| heat78 | H |1000|1000|0000|0100|1011|0100|0011
-| heat80 | H |1000|1000|0000|0100|1100|0100|0100
-| heat82 | H |1000|1000|0000|0100|1101|0100|0101
-| heat84 | H |1000|1000|0000|0100|1110|0100|0110
-| heat86 | H |1000|1000|0000|0100|1111|0100|0111
diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
index 9697745e1..d5282f348 100644
--- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
+++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
@@ -32,22 +32,27 @@
*/
#include
+//#define NO_LED_FEEDBACK_CODE // Saves 276 bytes program memory
+
/*
- * LG2 has different header timing and a shorter bit time
- * Known LG remote controls, which uses LG2 protocol are:
+ * LG has different header timing and a shorter bit time
+ * Known LG remote controls, which uses LG protocol are:
* AKB75215403
* AKB74955603
* AKB73757604:
*/
-//#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol
#define NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU 5
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+
+//#define NO_LED_FEEDBACK_CODE // Saves 214 bytes program memory
#define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver.
//#define DEBUG // Activate this for more output from the LG-AC driver.
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
@@ -65,18 +70,21 @@ 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_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!
+
+#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_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
/*
- * The IR library setup. That's all!
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
*/
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
-
Serial.println();
MyLG_Aircondition.setType(LG_IS_WALL_TYPE);
diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendProntoDemo/PinDefinitionsAndMore.h
+++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino
index ba92eff21..963a22693 100644
--- a/examples/SendProntoDemo/SendProntoDemo.ino
+++ b/examples/SendProntoDemo/SendProntoDemo.ino
@@ -32,9 +32,13 @@
*/
#include
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+
+//#define NO_LED_FEEDBACK_CODE // Saves 266 bytes program memory
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
#define NUMBER_OF_REPEATS 3U
@@ -57,14 +61,21 @@ IRsend irsend;
void setup() {
Serial.begin(115200);
- while (!Serial)
- ;
+
+#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_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
}
void loop() {
diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SendRawDemo/PinDefinitionsAndMore.h
+++ b/examples/SendRawDemo/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino
index 351148ada..5a1e59915 100644
--- a/examples/SendRawDemo/SendRawDemo.ino
+++ b/examples/SendRawDemo/SendRawDemo.ino
@@ -3,8 +3,7 @@
*
* This example shows how to send a RAW signal using the IRremote library.
* The example signal is actually a 32 bit NEC signal.
- * Remote Control button: LGTV Power On/Off.
- * Hex Value: 0x20DF10EF, 32 bits
+ * Protocol=NEC Address=0x4 Command=0x18 Raw-Data=0xE718FB04 32 bits LSB first
*
* If it is a supported protocol, it is more efficient to use the protocol send function
* (here sendNEC) to send the signal.
@@ -14,7 +13,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2022 Armin Joachimsmeyer
+ * Copyright (c) 2020-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
@@ -37,34 +36,42 @@
*/
#include
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-//#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory
+//#define NO_LED_FEEDBACK_CODE // Saves 220 bytes program memory
//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include
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_attiny3217)
+
+#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_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
}
/*
- * NEC address=0xFB0C, command=0x18
+ * NEC address=0x04 (0xFB04), command=0x18 (0xE718)
*
- * This is data in byte format.
+ * This is the raw data array in byte format.
* The uint8_t/byte elements contain the number of ticks in 50 us.
* The uint16_t format contains the (number of ticks * 50) if generated by IRremote,
* so the uint16_t format has exact the same resolution but requires double space.
@@ -72,49 +79,52 @@ void setup() {
* e.g. use 560 (instead of 11 * 50) for NEC or use 432 for Panasonic. But in this cases,
* you better use the timing generation functions e.g. sendNEC() directly.
*/
-const uint8_t rawDataP[]
-#if defined(__AVR__)
-PROGMEM
-#endif
-= { 180, 90 /*Start bit*/, 11, 11, 11, 11, 11, 34, 11, 34/*0011 0xC of 16 bit address LSB first*/, 11, 11, 11, 11, 11, 11, 11,
+const uint8_t rawDataP[] PROGMEM
+= { 180, 90 /*Start bit*/, 11, 11, 11, 11, 11, 34, 11, 11/*0010 0x4 of 8 bit address LSB first*/, 11, 11, 11, 11, 11, 11, 11,
11/*0000*/, 11, 34, 11, 34, 11, 11, 11, 34/*1101 0xB*/, 11, 34, 11, 34, 11, 34, 11, 34/*1111*/, 11, 11, 11, 11, 11, 11, 11,
34/*0001 0x08 of command LSB first*/, 11, 34, 11, 11, 11, 11, 11, 11/*1000 0x01*/, 11, 34, 11, 34, 11, 34, 11,
11/*1110 Inverted 8 of command*/, 11, 11, 11, 34, 11, 34, 11, 34/*0111 inverted 1 of command*/, 11 /*stop bit*/};
+/*
+ * The same frame as above. Values are NOT multiple of 50, but are taken from the NEC timing definitions
+ */
+const uint16_t rawData[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
+ 560/*0010 0x4 of 8 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560,
+ 560, 1690/*1101 0xB - inverted 0x04*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111 - inverted 0*/, 560, 560, 560, 560,
+ 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 1690, 560, 560, 560, 560, 560, 560/*1000 0x01*/, 560, 1690, 560,
+ 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 560, 560, 1690, 560, 1690, 560,
+ 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
+
void loop() {
-#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
+#if FLASHEND > 0x1FFF // For more than 8k flash => not for ATtiny85 etc.
/*
* Send hand crafted data from RAM
- * The values are NOT multiple of 50, but are taken from the NEC timing definitions
*/
- Serial.println(F("Send NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)"));
+ Serial.println(F("Send NEC 8 bit address=0x04 (0xFB04) and command 0x18 (0xE718) with exact timing (16 bit array format)"));
Serial.flush();
-
- const uint16_t rawData[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
- 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560,
- 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560,
- 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560, 1690, 560,
- 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111 inverted 0 of command*/,
- 560 /*stop bit*/}; // Using exact NEC timing
IrSender.sendRaw(rawData, sizeof(rawData) / sizeof(rawData[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
- delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
+ delay(1000); // delay must be greater than 8 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
+
#endif
/*
* Send byte data direct from FLASH
* Note the approach used to automatically calculate the size of the array.
*/
- Serial.println(F("Send NEC 16 bit address 0xFB0C and data 0x18 with (50 us) tick resolution timing (8 bit array format) "));
+ Serial.println(F("Send NEC 8 bit address 0x04 and command 0x18 with (50 us) tick resolution timing (8 bit array format) "));
Serial.flush();
IrSender.sendRaw_P(rawDataP, sizeof(rawDataP) / sizeof(rawDataP[0]), NEC_KHZ);
- delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
+ delay(1000); // delay must be greater than 8 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
- Serial.println(F("Send NEC 16 bit address 0x0102, 8 bit data 0x34 with generated timing"));
+ /*
+ * Send the same frame using NEC encoder
+ */
+ Serial.println(F("Send NEC 16 bit address 0x04, 8 bit command 0x18 with NEC encoder"));
Serial.flush();
- IrSender.sendNEC(0x0102, 0x34, 0);
+ IrSender.sendNEC(0x04, 0x18, 0);
delay(3000);
}
diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SimpleReceiver/PinDefinitionsAndMore.h
+++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino
index 12b950b2c..4c0aeaea1 100644
--- a/examples/SimpleReceiver/SimpleReceiver.ino
+++ b/examples/SimpleReceiver/SimpleReceiver.ino
@@ -1,14 +1,15 @@
/*
* SimpleReceiver.cpp
*
- * Demonstrates receiving NEC IR codes with IRremote
+ * Demonstrates receiving ONLY NEC protocol IR codes with IRremote
+ * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 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
@@ -30,47 +31,55 @@
************************************************************************************
*/
+#include
+
/*
* Specify which protocol(s) should be used for decoding.
- * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
+ * If no protocol is defined, all protocols (except BEO / Bang&Olufsen) are active.
* This must be done before the #include
+ * In alphabetic order
*/
-//#define DECODE_DENON // Includes Sharp
-//#define DECODE_JVC
-//#define DECODE_KASEIKYO
-//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
-//#define DECODE_LG
-#define DECODE_NEC // Includes Apple and Onkyo
-//#define DECODE_SAMSUNG
-//#define DECODE_SONY
-//#define DECODE_RC5
-//#define DECODE_RC6
-
-//#define DECODE_BOSEWAVE
-//#define DECODE_LEGO_PF
-//#define DECODE_MAGIQUEST
-//#define DECODE_WHYNTER
-//#define DECODE_FAST
-
-//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
-//#define DECODE_HASH // special decoder for all protocols
-
-//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
+//#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328
+//#define DECODE_JVC // ~ 200 bytes
+//#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes
+//#define DECODE_LG // ~ 400 bytes
+//#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes
+//#define DECODE_SAMSUNG // ~ 300 bytes
+//#define DECODE_SONY // ~ 175 bytes
+//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes
+//#define DECODE_RC6 // ~ 375 bytes
+
+// Universal protocol decoder
+//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes
+//#define DECODE_HASH // special decoder for all protocols ~ 250 bytes
+
+// Exotic protocol decoder
+//#define DECODE_BOSEWAVE // ~ 140 bytes
+//#define DECODE_FAST // ~ 135 bytes
+//#define DECODE_LEGO_PF // ~ 300 bytes
+//#define DECODE_MAGIQUEST // ~ 270 bytes
+//#define DECODE_MARANTZ // RC5 + MARANTZ: ~ 425 bytes
+//#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command. ~ 175 bytes
+//#define DECODE_WHYNTER // ~ 90 bytes
+
+//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY! ~ 430 bytes
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-//#define RAW_BUFFER_LENGTH 180 // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
-#include
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+#include // include the library
/*
- * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
+ * Using the function printActiveIRProtocols() requires additional 318 bytes program memory
+ * Using the function printIRResultShort() requires additional 1436 bytes program memory
+ * Using the function printIRSendUsage() requires additional 2568 bytes program memory
+ * Because these 3 functions all share common code, using all 3 functions requires only additional 2884 bytes program memory
*/
-#include "PinDefinitionsAndMore.h"
-#include // include the library
-
void setup() {
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_IRREMOTE));
@@ -78,7 +87,7 @@ void setup() {
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.print(F("Ready to receive IR signals of protocols: "));
- printActiveIRProtocols(&Serial);
+ printActiveIRProtocols(&Serial); // Requires additional 318 bytes program memory
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}
@@ -94,30 +103,35 @@ void loop() {
if (IrReceiver.decode()) {
/*
- * Print a short summary of received data
+ * Print a summary of received data
*/
- IrReceiver.printIRResultShort(&Serial);
- IrReceiver.printIRSendUsage(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
- // We have an unknown protocol here, print more info
+ // We have an unknown protocol here, print extended info
IrReceiver.printIRResultRawFormatted(&Serial, true);
+
+ IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
+ } else {
+ IrReceiver.resume(); // Early enable receiving of the next IR frame
+
+ IrReceiver.printIRResultShort(&Serial); // Requires additional 1436 bytes program memory
+ IrReceiver.printIRSendUsage(&Serial); // Calls printIRResultShort() and other functions, if protocol is UNKNOWN
}
Serial.println();
- /*
- * !!!Important!!! Enable receiving of the next value,
- * since receiving has stopped after the end of the current received data packet.
- */
- IrReceiver.resume(); // Enable receiving of the next value
-
/*
* Finally, check the received data and perform actions according to the received command
*/
- if (IrReceiver.decodedIRData.command == 0x10) {
- // do something
- } else if (IrReceiver.decodedIRData.command == 0x11) {
- // do something else
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ Serial.println(F("Received command 0x10."));
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ Serial.println(F("Received command 0x11."));
+ // do something else
+ }
}
}
}
diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..d3dd74992
--- /dev/null
+++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h
@@ -0,0 +1,366 @@
+/*
+ * 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
+ *
+ * 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)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
+#endif
+
+#if !defined (FLASHEND)
+#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
+#endif
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
+#endif
+#if !defined (RAMSIZE)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
+#endif
diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino
new file mode 100644
index 000000000..27c0be7f9
--- /dev/null
+++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino
@@ -0,0 +1,102 @@
+/*
+ * SimpleReceiverForHashCodes.cpp
+ *
+ * Demonstrates receiving hash codes of unknown protocols with IRremote
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ ************************************************************************************
+ * MIT License
+ *
+ * Copyright (c) 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" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+
+/*
+ * Specify which protocol(s) should be used for decoding.
+ * This must be done before the #include
+ */
+#define DECODE_HASH // special decoder for all protocols
+#if !defined(RAW_BUFFER_LENGTH)
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE >= 0x400
+// Here we have 1 k RAM or more
+#define RAW_BUFFER_LENGTH 750
+# elif RAMSIZE >= 0x800
+// Here we have 2 k RAM or more
+#define RAW_BUFFER_LENGTH 1000 // Especially useful for unknown and probably long protocols
+# endif
+#endif
+//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
+
+#include // include the library
+
+void setup() {
+ 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_IRREMOTE));
+
+ // 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);
+
+ Serial.println(F("Ready to receive unknown IR signals at pin " STR(IR_RECEIVE_PIN) " and decode it with hash decoder."));
+}
+
+void loop() {
+ /*
+ * Check if received data is available and if yes, try to decode it.
+ * Decoded hash result is in IrReceiver.decodedIRData.decodedRawData
+ */
+ if (IrReceiver.available()) {
+ IrReceiver.initDecodedIRData(); // is required, if we do not call decode();
+ IrReceiver.decodeHash();
+ IrReceiver.resume(); // Early enable receiving of the next IR frame
+ /*
+ * Print a summary and then timing of received data
+ */
+ IrReceiver.printIRResultShort(&Serial);
+ IrReceiver.printIRResultRawFormatted(&Serial, true);
+
+ Serial.println();
+
+ /*
+ * Finally, check the received data and perform actions according to the received command
+ */
+ auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ Serial.print(F("Raw data received are 0x"));
+ Serial.println(tDecodedRawData);
+
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ // do something else
+ }
+ }
+ }
+}
diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/SimpleSender/PinDefinitionsAndMore.h
+++ b/examples/SimpleSender/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino
index 0ea7ece3c..ac372582e 100644
--- a/examples/SimpleSender/SimpleSender.ino
+++ b/examples/SimpleSender/SimpleSender.ino
@@ -3,9 +3,9 @@
*
* Demonstrates sending IR codes in standard format with address and command
* An extended example for sending can be found as SendDemo.
+ * Sending IR codes using several pins for sending is implements in the MultipleSendPins example.
*
- * Copyright (C) 2020-2022 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2020-2026 Armin Joachimsmeyer
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -13,14 +13,14 @@
*/
#include
-#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory
-/*
- * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
- */
-#include "PinDefinitionsAndMore.h"
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include // include the library
void setup() {
@@ -34,10 +34,10 @@ void setup() {
Serial.println(IR_SEND_PIN);
/*
- * The IR library setup. That's all!
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
*/
-// IrSender.begin(); // Start with IR_SEND_PIN as send pin and if NO_LED_FEEDBACK_CODE is NOT defined, enable feedback LED at default feedback LED pin
- IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin and disable feedback LED at default feedback LED pin
}
/*
@@ -66,6 +66,18 @@ void loop() {
// Receiver output for the first loop must be: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
IrSender.sendNEC(0x00, sCommand, sRepeats);
+ /*
+ * If you want to send a raw HEX value directly like e.g. 0xCB340102 you must use sendNECRaw()
+ */
+// Serial.println(F("Send 32 bit LSB 0xCB340102 with NECRaw()"));
+// IrSender.sendNECRaw(0xCB340102, sRepeats);
+
+ /*
+ * If you want to send an "old" MSB HEX value used by IRremote versions before 3.0 like e.g. 0x40802CD3 you must use sendNECMSB()
+ */
+// Serial.println(F("Send old 32 bit MSB 0x40802CD3 with sendNECMSB()"));
+// IrSender.sendNECMSB(0x40802CD3, 32, sRepeats);
+
/*
* Increment send values
*/
diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..d3dd74992
--- /dev/null
+++ b/examples/TinyReceiver/PinDefinitionsAndMore.h
@@ -0,0 +1,366 @@
+/*
+ * 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
+ *
+ * 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)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
+#endif
+
+#if !defined (FLASHEND)
+#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
+#endif
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
+#endif
+#if !defined (RAMSIZE)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
+#endif
diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino
index cbf6188f3..f3465d5aa 100644
--- a/examples/TinyReceiver/TinyReceiver.ino
+++ b/examples/TinyReceiver/TinyReceiver.ino
@@ -4,29 +4,29 @@
* Small memory footprint and no timer usage!
*
* Receives IR protocol data of NEC protocol using pin change interrupts.
- * On complete received IR command the function handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, uint8_t aFlags)
- * is called in Interrupt context but with interrupts being enabled to enable use of delay() etc.
+ * 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,
- * so if you require longer action, save the data (address + command) and handle it in the main loop.
* !!!!!!!!!!!!!!!!!!!!!
*
* 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.
+ * - 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 IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ * This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2023 Armin Joachimsmeyer
+ * 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
@@ -50,65 +50,37 @@
#include
-/*
- * Set sensible receive pin for different CPU's
- */
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
-/*
- * This program runs on 1 MHz CPU clock :-) and is requires only 1550 bytes program memory using ATTiny core
- */
-#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut" - Saves up to 700 bytes program memory and 70 bytes RAM for ATtinyCore
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
-#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
-# else
-#define IR_RECEIVE_PIN 0 // PCINT0
-# endif
-#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
-#define IR_RECEIVE_PIN 10
-#elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
-#define IR_RECEIVE_PIN 21 // INT0
-#elif defined(ESP8266)
-#define IR_RECEIVE_PIN 14 // D5
-#elif defined(CONFIG_IDF_TARGET_ESP32C3)
-#define IR_RECEIVE_PIN 8
-#elif defined(ESP32)
-#define IR_RECEIVE_PIN 15
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
-#define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
-#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
-#define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
-#else
-#define IR_RECEIVE_PIN 2 // INT0
-//#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.
-#endif
-
//#define DEBUG // to see if attachInterrupt is used
//#define TRACE // to see the state of the ISR state machine
/*
- * Second: include the code and compile it.
+ * Protocol selection
*/
-//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
+//#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 (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO.
-//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
-#include "TinyIRReceiver.hpp"
-
+//#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.
/*
- * Helper macro for getting a macro definition as string
+ * Set compile options to modify the generated code.
*/
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
-#endif
-
-volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
+//#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 "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
+#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_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!
+
+#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();
@@ -116,7 +88,7 @@ void setup() {
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()) {
+ if (!initPCIInterruptForTinyIRReceiver()) {
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)
@@ -127,64 +99,70 @@ void setup() {
}
void loop() {
- if (sCallbackData.justWritten) {
- sCallbackData.justWritten = false;
-#if defined(USE_FAST_PROTOCOL)
- Serial.print(F("Command=0x"));
-#else
+ if (TinyIRReceiverDecode()) {
+ /*
+ * 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(sCallbackData.Address, HEX);
- Serial.print(F(" Command=0x"));
+ Serial.print(TinyIRReceiverData.Address, HEX);
+ Serial.print(' ');
#endif
- Serial.print(sCallbackData.Command, HEX);
- if (sCallbackData.Flags == IRDATA_FLAGS_IS_REPEAT) {
+
+ Serial.print(F("Command=0x"));
+ Serial.print(TinyIRReceiverData.Command, HEX);
+ if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F(" Repeat"));
}
- if (sCallbackData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
+ 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 :-)
+ */
}
/*
- * This is the function, which is called if a complete command was received
- * It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here
+ * Optional code, if you require a callback
*/
-#if defined(ESP8266) || defined(ESP32)
+#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
-
-#if defined(USE_FAST_PROTOCOL)
-void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags)
-#elif defined(USE_ONKYO_PROTOCOL)
-void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags)
-#else
-void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags)
-#endif
- {
-#if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
- // Copy data for main loop, this is the recommended way for handling a callback :-)
-# if !defined(USE_FAST_PROTOCOL)
- sCallbackData.Address = aAddress;
# endif
- sCallbackData.Command = aCommand;
- sCallbackData.Flags = aFlags;
- sCallbackData.justWritten = true;
-#else
+void handleReceivedTinyIRData() {
+# if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
/*
- * Printing is not allowed in ISR context for any kind of RTOS
+ * 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!)
*/
- // 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)
- printTinyReceiverResultMinimal(&Serial, aCommand, aFlags);
# else
- printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags);
+ // 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
+ printTinyIRReceiverResultMinimal(&Serial);
# endif
-#endif
+ if (TinyIRReceiverData.Command == 0x10) {
+ // do something SHORT here
+ } else if (TinyIRReceiverData.Command == 0x11) {
+ // do something SHORT here too
+ }
}
+#endif
+
diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..d3dd74992
--- /dev/null
+++ b/examples/TinySender/PinDefinitionsAndMore.h
@@ -0,0 +1,366 @@
+/*
+ * 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
+ *
+ * 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)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
+#endif
+
+#if !defined (FLASHEND)
+#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
+#endif
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
+#endif
+#if !defined (RAMSIZE)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
+#endif
diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino
index 39ff3c4d7..45d79af76 100644
--- a/examples/TinySender/TinySender.ino
+++ b/examples/TinySender/TinySender.ino
@@ -1,10 +1,12 @@
/*
* TinySender.cpp
*
- * Example for sending FAST or NEC protocol using TinyIR.
+ * 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).
*
- * NEC protocol codes are sent in standard format with 8bit address and 8 bit command as in SimpleSender example.
- * 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:
@@ -15,13 +17,13 @@
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
- * 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.
+ * This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2023 Armin Joachimsmeyer
+ * 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
@@ -44,16 +46,10 @@
*/
#include
-//#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command
-//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
-//#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 (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC.
-//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#include "TinyIRSender.hpp"
-#define IR_SEND_PIN 3
-
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
@@ -82,29 +78,47 @@ void loop() {
*/
Serial.println();
Serial.print(F("Send now:"));
-#if defined(USE_FAST_PROTOCOL)
Serial.print(F(" address=0x"));
Serial.print(sAddress, HEX);
-#endif
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.print(sRepeats);
Serial.println();
-#if defined(USE_FAST_PROTOCOL)
- Serial.println(F("Send FAST with 8 bit address"));
+ // 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);
-#elif defined(USE_ONKYO_PROTOCOL)
+
+ // 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);
-#else
- Serial.println(F("Send NEC with 8 bit address"));
+
+ // 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);
-#endif
+ sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true);
+
/*
* Increment send values
* Also increment address just for demonstration, which normally makes no sense
diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h
index ce84aa482..d3dd74992 100644
--- a/examples/UnitTest/PinDefinitionsAndMore.h
+++ b/examples/UnitTest/PinDefinitionsAndMore.h
@@ -4,8 +4,7 @@
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
- * armin.joachimsmeyer@gmail.com
+ * Copyright (C) 2021-2026 Armin Joachimsmeyer
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@@ -35,21 +34,24 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * 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
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
- * ESP32 15 4 27
- * BluePill PA6 PA7 PA3
+ * 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__) // Digispark board. For use with ATTinyCore.
+#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.
@@ -59,28 +61,30 @@
# 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)
+# 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
-# else
+# 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
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# 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__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# 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
@@ -88,39 +92,42 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# 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/
-// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
-#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
-#define IR_SEND_PIN PIN_PA2 // 19
-#define TONE_PIN PIN_PA3 // 20
-#define APPLICATION_PIN PIN_PA0 // 0
+// 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 for TinyCore32
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#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_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
-#define IR_SEND_PIN PIN_PA3 // 10
-#define TONE_PIN PIN_PA5 // 1
-#define APPLICATION_PIN PIN_PA4 // 0
-
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
-#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
+#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
-#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
-#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+# 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__) \
@@ -153,6 +160,15 @@
# 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
@@ -162,21 +178,41 @@
#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)
-#define IR_INPUT_PIN 8
-#define IR_SEND_PIN 9
-#define TONE_PIN 10 // ADC2_0
-#define APPLICATION_PIN 11
+#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_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# 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){
@@ -199,7 +235,7 @@ void noTone(uint8_t aPinNumber){
#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) // BluePill
+#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"
@@ -219,7 +255,8 @@ void noTone(uint8_t aPinNumber){
#define IR_SEND_PIN 12
#define TONE_PIN 5
-#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE
+#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
@@ -240,7 +277,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -266,7 +303,11 @@ void noTone(uint8_t aPinNumber){
#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
@@ -299,7 +340,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#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
@@ -309,28 +350,17 @@ void noTone(uint8_t aPinNumber){
#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 warning in IRTimer.hpp
-# endif
+#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER)
+#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
-#if !defined (RAMEND)
-#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined
+
+#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART)
+#define RAMSIZE (RAMEND - RAMSTART + 1) //
#endif
#if !defined (RAMSIZE)
-#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
-#endif
-
-/*
- * Helper macro for getting a macro definition as string
- */
-#if !defined(STR_HELPER)
-#define STR_HELPER(x) #x
-#define STR(x) STR_HELPER(x)
+#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined
#endif
diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino
index b9a88d11b..f88f26227 100644
--- a/examples/UnitTest/UnitTest.ino
+++ b/examples/UnitTest/UnitTest.ino
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-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
@@ -33,44 +33,58 @@
#include
-#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
+//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 24 bytes program memory.
+//#define USE_STRICT_DECODER // Check for additional required characteristics of protocol timing. Requires 300 additional bytes program memory.
+//#define USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin.
+//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
+//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
+//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal.
+#define NO_LED_FEEDBACK_CODE // Saves 270 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 176 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 38 bytes program memory
+//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us
+
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER.
#if !defined(RAW_BUFFER_LENGTH)
-# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
-//#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
-#define RAW_BUFFER_LENGTH 150 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
-# else
-#define RAW_BUFFER_LENGTH 200 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
+// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
+# if RAMSIZE <= 0x400
+// Here we have 1 k RAM or less
+#define RAW_BUFFER_LENGTH 360
+# elif RAMSIZE <= 0x800
+// Here we have 2 k RAM or less, otherwise use default of 750
+#define RAW_BUFFER_LENGTH 400 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten.
# endif
#endif
-//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
-//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
-//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
-//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory
-// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
//#define USE_MSB_DECODING_FOR_DISTANCE_DECODER
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
+
+// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // 40 inhibits the decoding of the short B&O marks of 250 us.
+
+//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
//#define TRACE // For internal usage
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#if FLASHEND >= 0x1FFF // For 8k flash or more, like ATtiny85
#define DECODE_DENON // Includes Sharp
-#define DECODE_KASEIKYO
-#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
-#define DECODE_NEC // Includes Apple and Onkyo
+#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes
+#define DECODE_NEC // Includes Apple and Onkyo ~ 1050 bytes
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
#define DECODE_JVC
-#define DECODE_RC5
-#define DECODE_RC6
+#define DECODE_RC5 // with DECODE_MARANTZ ~ 1270
+#define DECODE_MARANTZ
+#define DECODE_RC6 // ~ 940 bytes
-#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
+#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2430 bytes
#define DECODE_HASH // special decoder for all protocols
#endif
@@ -78,31 +92,44 @@
#define DECODE_SONY
#define DECODE_SAMSUNG
#define DECODE_LG
-
-#define DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here.
-//#define ENABLE_BEO_WITHOUT_FRAME_GAP // For successful unit testing we must see the warning at ir_BangOlufsen.hpp:88:2
-#if defined(DECODE_BEO)
-#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer
-#define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz here (instead of 455 kHz).
+#define DECODE_LEGO_PF // LEGO is skipped, since it is difficult to receive because of its short marks and spaces
+
+#define DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here. ~ 1340 bytes
+//#define ENABLE_BEO_WITHOUT_FRAME_GAP // !!!For successful unit testing we must see the warning at ir_BangOlufsen.hpp:100:2!!!
+# if defined(DECODE_BEO)
+#define RECORD_GAP_MICROS 16000 // Force to get the complete frame including the 3. space of 15 ms in the receive buffer
+#define SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING // We know, what we do here :-)
+#define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz instead of 455 kHz in order to be able to test it
+# endif
#endif
-#define DECODE_BOSEWAVE
-//#define DECODE_LEGO_PF
-#define DECODE_MAGIQUEST
+#define DECODE_BOSEWAVE // ~ 250 bytes
+#define DECODE_MAGIQUEST // ~ 460 bytes
+#define DECODE_OPENLASIR // ~ 330 bytes
+#define DECODE_FAST // ~ 210 bytes
+
//#define DECODE_WHYNTER
-#define DECODE_FAST
-#endif
+//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
+
+#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints the reason which prevents data to be decoded as distance width data
#include
-#if defined(APPLICATION_PIN)
+#include "TinyIRSender.hpp"
+
+#if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN)
#define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data
#else
#define DEBUG_BUTTON_PIN 6
#endif
+#if defined(ESP32) && defined(DEBUG_BUTTON_PIN)
+# if !digitalPinIsValid(DEBUG_BUTTON_PIN)
+#undef DEBUG_BUTTON_PIN // DEBUG_BUTTON_PIN number is not valid, so delete definition to disable further usage
+# endif
+#endif
-#define DELAY_AFTER_SEND 1000
-#define DELAY_AFTER_LOOP 5000
+#define DELAY_AFTER_SEND 700
+#define DELAY_AFTER_LOOP 3000
#if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
#error Unit test cannot run if SEND_PWM_BY_TIMER is enabled i.e. receive timer us also used by send
@@ -114,12 +141,38 @@
volatile bool sDataJustReceived = false;
void ReceiveCompleteCallbackHandler();
+#if __INT_WIDTH__ < 32
+//IRDecodedRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
+uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/
+0x10, 0xA0, 0x0, 0x0, /*0xA010*/}; // Define tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010}
+#endif
+
+// if this definition is contained in a function, the address, the compiler uses is wrong :-(
+const uint16_t rawIRTimingsNEC[]
+#if defined(__AVR__)
+PROGMEM // this crashes on ESP8266
+#endif
+= { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560,
+ 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560,
+ 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560,
+ 560/*0000 0x00*/, 560, 1690, 560, 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690,
+ 560, 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
+
void setup() {
+#if defined(DEBUG_BUTTON_PIN)
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
+#endif
Serial.begin(115200);
-#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || 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!
+
+#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_IRREMOTE));
@@ -136,26 +189,44 @@ void setup() {
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#endif
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
+ Serial.println(F("Use ReceiveCompleteCallback"));
+ Serial.println(F("Receive buffer length is " STR(RAW_BUFFER_LENGTH)));
+
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
# if defined(IR_SEND_PIN_STRING)
- Serial.println(F("at pin " IR_SEND_PIN_STRING));
+ Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
# endif
#else
- IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
- Serial.println(F("Send IR signals at pin 3"));
+ // Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN
+ uint8_t tSendPin = 3;
+ IrSender.begin(tSendPin);// Specify send pin and use feedback LED at default feedback LED pin
+ // You can change send pin later with IrSender.setSendPin();
+
+ Serial.print(F("Send IR signals at pin "));
+ Serial.println(tSendPin);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
+# if defined(DEBUG_BUTTON_PIN)
Serial.print(F("If you connect debug pin "));
-# if defined(APPLICATION_PIN_STRING)
- Serial.print(APPLICATION_PIN_STRING);
-# else
Serial.print(DEBUG_BUTTON_PIN);
-# endif
Serial.println(F(" to ground, raw data is always printed"));
+# endif
// For esp32 we use PWM generation by ledcWrite() for each pin.
# if !defined(SEND_PWM_BY_TIMER)
@@ -175,14 +246,19 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
delay(DELAY_AFTER_SEND);
}
-void checkReceivedRawData(IRRawDataType aRawData) {
+void checkReceivedRawData(IRDecodedRawDataType aRawData) {
// wait until signal has received
while (!sDataJustReceived) {
};
@@ -197,11 +273,16 @@ void checkReceivedRawData(IRRawDataType aRawData) {
IrReceiver.printIRResultMinimal(&Serial);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
- // We have an unknown protocol, print more info
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
+ // We have an unknown protocol or debug button is held low, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
-#endif
+#endif // FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
+
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
if (IrReceiver.decodedIRData.decodedRawData != aRawData) {
Serial.print(F("ERROR: Received data=0x"));
@@ -217,6 +298,8 @@ void checkReceivedRawData(IRRawDataType aRawData) {
PrintULL::print(&Serial, aRawData, HEX);
#endif
Serial.println();
+ IrReceiver.printIRResultAsCArray(&Serial, false, false); // To be able to easily compare received with sent data
+ Serial.println();
}
}
IrReceiver.resume();
@@ -227,7 +310,7 @@ void checkReceivedRawData(IRRawDataType aRawData) {
}
#if defined(DECODE_DISTANCE_WIDTH)
-void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize) {
+void checkReceivedArray(IRDecodedRawDataType *aRawDataArrayPointer, uint8_t aArraySize) {
// wait until signal has received
while (!sDataJustReceived) {
};
@@ -242,8 +325,12 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
IrReceiver.printIRResultMinimal(&Serial);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
- // We have an unknown protocol, print more info
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
+ // We have an unknown protocol or debug button is held low, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
@@ -259,6 +346,7 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
# endif
Serial.print(F(" != sent data=0x"));
Serial.println(*aRawDataArrayPointer, HEX);
+ IrReceiver.printIRResultAsCArray(&Serial, false, false);
}
aRawDataArrayPointer++;
}
@@ -273,17 +361,45 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
/*
* Test callback function
- * Has the same functionality as available()
+ * Has the same functionality as a check with available()
*/
void ReceiveCompleteCallbackHandler() {
sDataJustReceived = true;
}
-void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
+/*
+ * Must be called after checkReceive, because it does not wait for signal to be received and does not call decode()
+ */
+void checkReceivedExtra(uint16_t aSentExtra) {
+ if (IrReceiver.decodedIRData.extra != aSentExtra) {
+ Serial.print(F("ERROR: Received extra=0x"));
+ Serial.print(IrReceiver.decodedIRData.extra, HEX);
+ Serial.print(F(" != sent extra=0x"));
+ Serial.println(aSentExtra, HEX);
+ }
+}
+
+void waitForReceived() {
// wait until signal has received
+ uint16_t tTimeoutCounter = 500; // gives 5 seconds timeout
while (!sDataJustReceived) {
- };
+ delay(10);
+ if (tTimeoutCounter == 0) {
+ Serial.println(F("Receive timeout happened"));
+ break;
+ }
+ tTimeoutCounter--;
+ }
sDataJustReceived = false;
+}
+
+/*
+ * @return true if NO error, false if error
+ */
+bool checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
+ bool tReturnValueIsSuccess = true;
+
+ waitForReceived();
if (IrReceiver.decode()) {
// Print a short summary of received data
@@ -300,13 +416,20 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
}
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
+ IrReceiver.resume(); // Early resume
+
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("ERROR: Unknown protocol"));
+ tReturnValueIsSuccess = false;
} else {
/*
* Check address
@@ -316,6 +439,7 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(F(" != sent address=0x"));
Serial.println(aSentAddress, HEX);
+ tReturnValueIsSuccess = false;
}
/*
* Check command
@@ -325,14 +449,17 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
Serial.print(IrReceiver.decodedIRData.command, HEX);
Serial.print(F(" != sent command=0x"));
Serial.println(aSentCommand, HEX);
+ tReturnValueIsSuccess = false;
}
}
- IrReceiver.resume();
} else {
Serial.println(F("No data received"));
+ tReturnValueIsSuccess = false;
+ IrReceiver.resume();
}
Serial.println();
+ return tReturnValueIsSuccess;
}
/*
@@ -344,7 +471,12 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
uint16_t sAddress = 0xFFF1;
uint8_t sCommand = 0x76;
uint16_t s16BitCommand = 0x9876;
-#define sRepeats 0 // no unit test for repeats
+/*
+ * Repeats cannot be automatically checked, because just the first frame is stored in receive buffer and all repeat frames are skipped.
+ * We cannot issue a resume() before sending of an repeat, because we use the blocking send*() functions.
+ * But an independent receiver could check it
+ */
+uint8_t sRepeats = 0;
void loop() {
/*
@@ -355,36 +487,131 @@ void loop() {
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
+ if (sRepeats > 0) {
+ Serial.print(F(" repeats="));
+ Serial.print(sRepeats);
+ }
+
Serial.println();
Serial.println();
- Serial.println(F("Send NEC with 8 bit address"));
+#if defined(DECODE_NEC)
+ /*
+ * Sending complete NEC frames as repeats to force decoding as NEC2 are tested here
+ */
+ Serial.print(F("Send NEC with 8 bit address"));
+ if (sRepeats > 0) {
+ Serial.print(F(" and complete NEC frames as repeats to force decoding as NEC2"));
+ }
+ Serial.println();
Serial.flush();
- IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats);
+ IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); // sending first frame -> decodes as NEC
checkReceive(sAddress & 0xFF, sCommand);
+
+ for (int8_t i = 0; i < sRepeats; i++) {
+# if defined(DEBUG_BUTTON_PIN)
+ if (digitalRead(DEBUG_BUTTON_PIN) != LOW) {
+ // If debug is enabled, printing time (50 ms) is sufficient as delay
+ delayMicroseconds(NEC_REPEAT_DISTANCE - 20000); // 20000 is just a guess
+ }
+# endif
+ IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); // sending repeat frames -> decodes as NEC2
+ checkReceive(sAddress & 0xFF, sCommand);
+ }
+
delay(DELAY_AFTER_SEND); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
Serial.println(F("Send NEC with 16 bit address"));
Serial.flush();
- IrSender.sendNEC(sAddress, sCommand, sRepeats);
+ IrSender.sendNEC(sAddress, sCommand, sRepeats); // no repeats
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send NEC2 with 16 bit address"));
+ Serial.println(F("Send NEC2 with 16 bit address")); // The only difference is the repeat
Serial.flush();
IrSender.sendNEC2(sAddress, sCommand, sRepeats);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
+#endif // defined(DECODE_NEC)
+
+#if FLASHEND >= 0x7FFF && RAMSIZE >= 0x600 // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc.
+ if (sCommand == 0x76) {
+ /*
+ * Do this only once at the first loop
+ */
+
+#if defined(DECODE_RC5)
+ /*
+ * Test minimal RC5X and maximal RC5 length
+ */
+ Serial.println(F("Send RC5 minimal length")); // 14
+ Serial.flush();
+ IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get minimal length
+ IrSender.sendRC5(0x0A, 0x6A, sRepeats, true); // use RC5X
+ checkReceive(0x0A, 0x6A);
+ delay(DELAY_AFTER_SEND / 2);
+
+ Serial.println(F("Send RC5 maximal length")); // 28
+ Serial.flush();
+ IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get maximal length
+ IrSender.sendRC5(0x1F, 0x3F, sRepeats, true);
+ checkReceive(0x1F, 0x3F);
+ delay(DELAY_AFTER_SEND / 2);
+
+ Serial.println(F("Send Marantz maximal length")); // 34
+ Serial.flush();
+ IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get maximal length
+ IrSender.sendRC5Marantz(0x1F, 0x3F, sRepeats, 0x3F, true);
+ if (checkReceive(0x1F, 0x3F)) {
+ checkReceivedExtra(0x3F);
+ }
+
+ delay(DELAY_AFTER_SEND);
+#endif // defined(DECODE_RC5)
+
+#if defined(DECODE_RC6)
+ /*
+ * Test minimal RC6 and maximal RC6A length
+ * Toggle bit does not make any difference for RC6A, because it is located between a 0 and a 1 bit
+ */
+ Serial.println(F("Send RC6 minimal length")); // 26
+ Serial.flush();
+ IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get minimal length
+ IrSender.sendRC6(0x55, 0x55, 0, true);
+ checkReceive(0x55, 0x55);
+ delay(DELAY_AFTER_SEND / 2);
+
+ Serial.println(F("Send RC6A maximal length")); // 72
+ Serial.flush();
+ IrSender.sendRC6A(0xFF, 0xFF, 0, 0x3FFF, true);
+ if (checkReceive(0xFF, 0xFF)) {
+ checkReceivedExtra(0x3FFF);
+ }
+ delay(DELAY_AFTER_SEND);
+#endif // defined(DECODE_RC6)
+
+ IRDecodedRawDataType tRawData[4];
-#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+ /*
+ * Test send usage for UNKNOWN protocol
+ */
+ const uint16_t rawIRTimings[] = { 9000, 4500/*Start bit*/, 500, 1000, 1000, 500, 500, 2000, 2000, 500, 500, 3000, 3000, 500,
+ 500, 250, 250, 500 };
+ Serial.println(F("Send arbitrary raw data with 1 repeat and exact timing (16 bit array format) with sendRaw()"));
+ Serial.flush();
+ IrSender.sendRaw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), NEC_KHZ, 80, 1); // Note the approach used to automatically calculate the size of the array.
+ waitForReceived();
+ IrReceiver.printIRResultRawFormatted(&Serial, true);
+ IrReceiver.resume();
+ delay(DELAY_AFTER_SEND);
- if (sAddress == 0xFFF1) {
-# if FLASHEND >= 0x7FFF // For 32k flash or more, like UNO. Code does not fit in program memory of ATtiny1604 etc.
+# if defined(DECODE_NEC)
/*
* Send constant values only once in this demo
*/
- Serial.println(F("Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
+ Serial.println(F("Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()"));
Serial.flush();
+ // This is copied to stack/ram internally
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
"0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */
"0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */
@@ -394,16 +621,14 @@ void loop() {
checkReceive(0x80, 0x45);
delay(DELAY_AFTER_SEND);
+ /*
+ * Test sending NEC protocol using sendRaw_P
+ */
Serial.println(
- F("Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)"));
+ F(
+ "Send NEC data with 8 bit address=0xFB04, command 0x08, 1 repeat and exact timing (16 bit array format) with sendRaw_P()"));
Serial.flush();
- const uint16_t irSignal[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
- 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690,
- 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560,
- 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560,
- 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560,
- 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
- IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
+ IrSender.sendRaw_P(rawIRTimingsNEC, sizeof(rawIRTimingsNEC) / sizeof(rawIRTimingsNEC[0]), NEC_KHZ, 110, 1); // Note the approach used to automatically calculate the size of the array.
checkReceive(0xFB04 & 0xFF, 0x08);
delay(DELAY_AFTER_SEND);
@@ -412,13 +637,14 @@ void loop() {
*/
Serial.println(F("Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)"));
Serial.flush();
- IrSender.sendNECRaw(0x03040102, sRepeats);
+ IrSender.sendNECRaw(0x03040102, 0);
checkReceive(0x0102, 0x304);
delay(DELAY_AFTER_SEND);
/*
* With Send sendNECMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte.
+ * Use bitreverse32Bit().
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
@@ -427,40 +653,40 @@ void loop() {
IrSender.sendNECMSB(0x40802CD3, 32, false);
checkReceive(0x0102, 0x34);
delay(DELAY_AFTER_SEND);
-# endif
+# endif // defined(DECODE_NEC)
-# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants"));
+# if defined(DECODE_KASEIKYO)
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432"));
Serial.flush();
# if __INT_WIDTH__ < 32
- IRRawDataType tRawData[] = { 0xB02002, 0xA010, 0x0 }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+ IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48,
+ NO_REPEATS); // Panasonic is a Kaseikyo variant
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+ IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
checkReceivedRawData(0xA010B02002);
# endif
delay(DELAY_AFTER_SEND);
/*
- * Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first
+ * Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first
*/
- Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance"));
- Serial.println(F(" LSB first"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400"));
+ Serial.println(F("-LSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
- IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST, 0,
- NO_REPEATS);
+ IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRDecodedRawDataType*) tRawDataPGM, 48,
+ PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
- 0, NO_REPEATS);
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedRawData(0xA010B02002);
# endif
delay(DELAY_AFTER_SEND);
// The same with MSB first. Use bit reversed raw data of LSB first part
- Serial.println(F(" MSB first"));
+ Serial.println(F("-MSB first"));
# if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
@@ -468,22 +694,23 @@ void loop() {
NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedRawData(0x40040D000805);
# endif
delay(DELAY_AFTER_SEND);
-# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
+# endif // defined(DECODE_KASEIKYO)
# if defined(DECODE_DISTANCE_WIDTH)
# if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- Serial.println(F("Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first"));
+ Serial.println(F("Send 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first 1=550|1700, 0=550|600"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x43D8613C; // MSB of tRawData[0] is sent first
tRawData[1] = 0x3BC3B;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, 0,
- NO_REPEATS);
+ NO_REPEATS);
checkReceivedArray(tRawData, 2);
# else
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
@@ -491,7 +718,7 @@ void loop() {
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first"));
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first 1=600|300, 0=300|600"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
# if __INT_WIDTH__ < 32
@@ -502,7 +729,7 @@ void loop() {
checkReceivedRawData(0x123456789ABC);
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 32 bit PulseWidth 0x43D8613C MSB first"));
+ Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first 1=600|300, 0=300|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x43D8613C, 32, PROTOCOL_IS_MSB_FIRST, 0, 0);
@@ -510,7 +737,7 @@ void loop() {
delay(DELAY_AFTER_SEND);
# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
@@ -520,28 +747,105 @@ void loop() {
NO_REPEATS);
checkReceivedArray(tRawData, 3);
# else
- IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
+ tRawData[0] = 0xAFEDCBA987654321;
+ tRawData[1] = 0x5A; // LSB of tRawData[0] is sent first
+ IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedArray(tRawData, 2);
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first"));
+ /*
+ * This one can be interpreted as 52 bit PulseDistance or 53 bit PulseWidth with inverted bits and bit timing.
+ Protocol=PulseWidth, Raw-Data=0x123456, 53 bits, LSB first, Gap=789450us, Duration=49100us
+ Send on a 8 bit platform with:
+ uint32_t tRawData[]={0x789ABCDE, 0x123456};
+ IrSender.sendPulseDistanceWidthFromArray(38, 300, 650, 600, 450, 300, 450, &tRawData[0], 53, PROTOCOL_IS_LSB_FIRST, , );
+ rawIRTimings[108]:
+ -789450
+ + 300,- 650
+ + 300,- 600 + 600,- 300 + 650,- 450 + 500,- 250
+ + 600,- 300 + 300,- 650 + 650,- 250 + 600,- 350
+ + 250,- 650 + 300,- 600 + 650,- 250 + 650,- 300
+ + 600,- 350 + 550,- 300 + 350,- 550 + 650,- 300
+ + 300,- 650 + 550,- 300 + 350,- 550 + 650,- 300
+ + 600,- 300 + 350,- 550 + 300,- 600 + 650,- 350
+ + 300,- 600 + 250,- 600 + 350,- 600 + 600,- 300
+ + 650,- 300 + 600,- 250 + 600,- 300 + 350,- 600
+ + 300,- 650 + 600,- 300 + 650,- 250 + 350,- 550
+ + 550,- 350 + 300,- 650 + 600,- 300 + 300,- 600
+ + 300,- 600 + 350,- 600 + 650,- 250 + 350,- 550
+ + 650,- 300 + 650,- 250 + 300,- 600 + 350,- 550
+ + 350,- 600 + 650,- 250 + 350,- 550 + 350,- 550
+ + 650
+ Duration=49100us
+ */
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300"));
Serial.flush();
- // Real PulseDistanceWidth (constant bit length) does not require a stop bit
+ // Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
# if __INT_WIDTH__ < 32
tRawData[1] = 0xDCBA9;
- IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 300, 600, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedArray(tRawData, 2);
# else
- IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 300, 600, 600, 300, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(0xDCBA987654321);
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first"));
+ Serial.println(
+ F(
+ "Send the same 52 bit PulseDistanceWidth but with inverse of 0xDCBA9 87654321 and with inverse timing 1=600|300, 0=300|600"));
+ Serial.flush();
+# if __INT_WIDTH__ < 32
+ tRawData[2] = ~tRawData[0];
+ tRawData[3] = ~tRawData[1];
+ IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ checkReceivedArray(tRawData, 2);
+# else
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ checkReceivedRawData(0xDCBA987654321);
+# endif
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500"));
+ Serial.flush();
+ // Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
+ IrSender.sendPulseDistanceWidth(38, 6000, 500, 500, 1500, 1500, 500, sCommand, 7, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ checkReceivedRawData(sCommand);
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275"));
+ Serial.flush();
+ IrSender.sendPulseDistanceWidth_P(&VeluxProtocolConstants, 0x654321, VELUX_BITS, 0);
+ /*
+ * We send 24 bit MSB first so bitreverse32Bit() >> 8
+ * We send without header, so >> 1.
+ * We send as pulse width so we must invert result, which is decoded as pulse distance
+ */
+ checkReceivedRawData((~(((bitreverse32Bit(0x654321)) >> 8) >> 1)) & 0x7FFFFF);
+#if false
+ Serial.print(F("bitreverse32Bit(0x654321) >> 8 =0x"));
+ Serial.print(bitreverse32Bit(0x654321) >> 8, HEX);
+ Serial.print(F(" >> 1 =0x"));
+ Serial.print((bitreverse32Bit(0x654321) >> 8) >> 1, HEX);
+ Serial.print(F(" ~ =0x"));
+ Serial.println((~((bitreverse32Bit(0x654321) >> 8) >> 1)) & 0x7FFFFF, HEX);
+#endif
+
+ delay(DELAY_AFTER_SEND);
+
+# if defined(DECODE_SONY)
+ Serial.println(F("Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600"));
+ Serial.flush();
+ IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, (sAddress << 7 | (sCommand & 0x7F)), SIRCS_12_PROTOCOL,
+ PROTOCOL_IS_LSB_FIRST, 0, 0);
+ checkReceive(sAddress & 0x1F, sCommand & 0x7F);
+ delay(DELAY_AFTER_SEND);
+# endif
+
+ Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 - timing ratio is 1:2"));
Serial.flush();
- // Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(0x87654321);
delay(DELAY_AFTER_SEND);
@@ -549,33 +853,52 @@ void loop() {
# endif // defined(DECODE_DISTANCE_WIDTH)
# if defined(DECODE_MAGIQUEST)
- Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first"));
+ Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864"));
Serial.flush();
# if __INT_WIDTH__ < 32
- tRawData[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left
- tRawData[1] = 0x017619; // We send only 23 instead of 24 bite here! 19 is the checksum
- IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData[0], 55, PROTOCOL_IS_MSB_FIRST, 0, 0);
+ IRDecodedRawDataType tRawData1[2];
+ tRawData1[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left
+ tRawData1[1] = 0x017619; // We send only 23 bits here! 0x19 is the checksum
+ IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData1[0], 55,
+ PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 0, 0);
# else
// 0xD79BFE00 is 0x6BCDFF00 is shifted 1 left
- IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST, 0, 0);
+ IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 0, 0);
# endif
checkReceive(0xFF00, 0x176);
if (IrReceiver.decodedIRData.decodedRawData != 0x6BCDFF00) {
Serial.print(F("ERROR: Received address=0x"));
-#if (__INT_WIDTH__ < 32)
+# if (__INT_WIDTH__ < 32)
Serial.print(IrReceiver.decodedIRData.decodedRawData, HEX);
-#else
+# else
PrintULL::print(&Serial, IrReceiver.decodedIRData.decodedRawData, HEX);
-#endif
+# endif
Serial.println(F(" != sent address=0x6BCDFF00"));
Serial.println();
}
delay(DELAY_AFTER_SEND);
# endif // defined(DECODE_MAGIQUEST)
+ } // end of once at first loop
- }
-#endif // if FLASHEND >= 0x3FFF
+# if defined(DECODE_NEC)
+ Serial.println(F("Send NEC with TinyIRSender"));
+ Serial.flush();
+ sendNEC(IR_SEND_PIN, (uint8_t) sAddress, sCommand, sRepeats); // Casting saves 18 bytes
+ checkReceive(sAddress & 0xFF, sCommand);
+ delay(DELAY_AFTER_SEND);
+# endif
+
+# if defined(DECODE_FAST)
+ Serial.println(F("Send FAST with TinyIRSender"));
+ Serial.flush();
+ sendFAST(IR_SEND_PIN, sCommand, sRepeats);
+ checkReceive(0, sCommand);
+ delay(DELAY_AFTER_SEND);
+# endif
+
+#endif // if FLASHEND >= 0x7FFF
+#if defined(DECODE_NEC)
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
Serial.flush();
IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, sRepeats);
@@ -587,18 +910,21 @@ void loop() {
IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
+#endif
-#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
+#if defined(DECODE_KASEIKYO)
Serial.println(F("Send Panasonic"));
Serial.flush();
IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID"));
+ Serial.println(F("Send Kaseikyo with extra=0x4711 as Vendor ID"));
Serial.flush();
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
- checkReceive(sAddress & 0xFFF, sCommand);
+ if (checkReceive(sAddress & 0xFFF, sCommand)) {
+ checkReceivedExtra(0x4711);
+ }
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo_Denon variant"));
@@ -609,13 +935,13 @@ void loop() {
#endif
#if defined(DECODE_DENON)
- Serial.println(F("Send Denon"));
+ Serial.println(F("Send Denon with 2 autorepeats after 45 ms")); // Only first frame is received!
Serial.flush();
IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Denon/Sharp variant"));
+ Serial.println(F("Send Denon/Sharp variant with 2 autorepeats after 45 ms"));
Serial.flush();
IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
@@ -625,7 +951,7 @@ void loop() {
#if defined(DECODE_SONY)
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
Serial.flush();
- IrSender.sendSony(sAddress & 0x1F, sCommand, sRepeats);
+ IrSender.sendSony(sAddress & 0x1F, sCommand, sRepeats); // SIRCS_12_PROTOCOL is default
checkReceive(sAddress & 0x1F, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
@@ -635,23 +961,36 @@ void loop() {
checkReceive(sAddress & 0xFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
+# if defined(DECODE_BEO)
+ // BEO sets RECORD_GAP_MICROS 16000 which leads to concatenating the Sony repeats
+ Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits and no repeats"));
+ Serial.flush();
+ IrSender.sendSony(sAddress & 0x1FFF, sCommand, 0, SIRCS_20_PROTOCOL);
+# else
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL);
+# endif
checkReceive(sAddress & 0x1FFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_SAMSUNG)
- Serial.println(F("Send Samsung 8 bit command"));
+ Serial.println(F("Send Samsung 8 bit command and 8 bit address"));
+ Serial.flush();
+ IrSender.sendSamsung(sAddress & 0xFF, sCommand, sRepeats);
+ checkReceive(sAddress & 0xFF, sCommand);
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send Samsung 8 bit command and 16 bit address"));
Serial.flush();
- IrSender.sendSamsung(sAddress, sCommand, sRepeats);
+ IrSender.sendSamsung16BitAddressAnd8BitCommand(sAddress, sCommand, sRepeats);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Samsung 16 bit command"));
+ Serial.println(F("Send Samsung 16 bit command and address"));
Serial.flush();
- IrSender.sendSamsung(sAddress, s16BitCommand, sRepeats);
+ IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats);
checkReceive(sAddress, s16BitCommand);
delay(DELAY_AFTER_SEND);
@@ -662,6 +1001,10 @@ void loop() {
delay(DELAY_AFTER_SEND);
#endif
+#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6)
+ IrSender.setNextToggleBitValueForRC5AndRC6(sCommand); // To modify start value of toggling for each loop. Only LSB is taken :-).
+#endif
+
#if defined(DECODE_RC5)
Serial.println(F("Send RC5"));
Serial.flush();
@@ -676,13 +1019,106 @@ void loop() {
delay(DELAY_AFTER_SEND);
#endif
+#if defined(DECODE_MARANTZ)
+ Serial.print(F("Send Marantz with RC5 and extra=0x"));
+ Serial.println(~sCommand & 0x3F, HEX);
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sRepeats, ~sCommand & 0x3F, true); // 5 address, 6 command bits
+ if (checkReceive(sAddress & 0x1F, sCommand & 0x3F)) {
+ checkReceivedExtra(~sCommand & 0x3F);
+ }
+ delay(DELAY_AFTER_SEND);
+
+ Serial.print(F("Send Marantz with RC5A and extra=0x"));
+ Serial.println(~sCommand & 0x3F, HEX);
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, ~sCommand & 0x3F, true); // 5 address, 7 command bits
+ if (checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40)) {
+ checkReceivedExtra(~sCommand & 0x3F);
+ }
+ delay(DELAY_AFTER_SEND);
+#endif
+
#if defined(DECODE_RC6)
Serial.println(F("Send RC6"));
- // RC6 check does not work stable without the flush
Serial.flush();
+
IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send RC6A with 14 bit and extra=0x2711"));
+ Serial.flush();
+ IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true);
+ if (checkReceive(sAddress & 0xFF, sCommand)) {
+ checkReceivedExtra(0x2711);
+ }
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_MAGIQUEST)
+ uint32_t tWandId = 0x6BCD0000 | (uint32_t) sAddress;
+ Serial.print(F("Send MagiQuest, WandId=0x"));
+ Serial.println(tWandId, HEX);
+ Serial.flush();
+ IrSender.sendMagiQuest(tWandId, s16BitCommand); // we have 31 bit address
+ if (checkReceive(sAddress, s16BitCommand & 0x1FF)) { // we have 9 bit command
+ checkReceivedExtra(0x6BCD);
+ }
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_OPENLASIR)
+ Serial.println(F("Send OpenLASIR mode fire and color orange, detected as ONKYO"));
+ Serial.flush();
+ IrSender.sendOpenLASIR(sAddress & 0xFF, sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE, sRepeats);
+ checkReceive(sAddress & 0xFF,
+ IrSender.computeOpenLASIRRawCommand(sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE));
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_LEGO_PF)
+ Serial.println(F("Send Lego with 2 channel and with 4 command bits"));
+ Serial.flush();
+ IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, false);
+ checkReceive(sAddress & 0x0F, (sCommand | (LEGO_MODE_COMBO << LEGO_COMMAND_BITS)) & 0x1F);
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_BEO)
+ Serial.println(F("Send 16 bit Bang&Olufsen - requires originally 455 kHz"));
+ Serial.flush();
+ IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats, 8); // send 8 bit command and 8 bit address / header
+# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
+ delay((RECORD_GAP_MICROS / 1000) + 1);
+ Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled"));
+ IrReceiver.printIRResultRawFormatted(&Serial, true);
+ Serial.println(F("- Now try to decode the first 6 entries, which results in rawData 0x0"));
+ uint8_t tOriginalRawlen = IrReceiver.irparams.rawlen;
+ IrReceiver.decodedIRData.rawlen = 6;
+ IrReceiver.irparams.rawlen = 6;
+ /*
+ * decode first part / AGC part of frame
+ */
+ IrReceiver.decode();
+ IrReceiver.printIRResultShort(&Serial); // -> Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first
+
+ if (tOriginalRawlen > 30) {
+ // Remove trailing 6 entries for second decode try
+ Serial.println();
+ Serial.println(
+ F(
+ "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode"));
+ IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6;
+ IrReceiver.irparams.rawlen = tOriginalRawlen - 6;
+ for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) {
+ IrReceiver.irparams.rawbuf[i] = IrReceiver.irparams.rawbuf[i + 6];
+ }
+ IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0];
+ checkReceive(sAddress & 0xFF, sCommand); // only 8 bit of address is sent
+ }
+# endif
+ delay(DELAY_AFTER_SEND);
#endif
/*
@@ -694,6 +1130,10 @@ void loop() {
IRSendData.command = sCommand;
IRSendData.flags = IRDATA_FLAGS_EMPTY;
+ Serial.println(F("Send next protocols with IrSender.write"));
+ Serial.println();
+ Serial.flush();
+
#if defined(DECODE_JVC)
IRSendData.protocol = JVC; // switch protocol
Serial.print(F("Send "));
@@ -708,57 +1148,16 @@ void loop() {
IRSendData.command = s16BitCommand; // LG support more than 8 bit command
#endif
-#if defined(DECODE_SAMSUNG)
- IRSendData.protocol = SAMSUNG;
- Serial.print(F("Send "));
- Serial.println(getProtocolString(IRSendData.protocol));
- Serial.flush();
- IrSender.write(&IRSendData, sRepeats);
- checkReceive(IRSendData.address, IRSendData.command);
- delay(DELAY_AFTER_SEND);
-#endif
-
#if defined(DECODE_LG)
IRSendData.protocol = LG;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
- IrSender.write(&IRSendData, sRepeats);
+ IrSender.write(&IRSendData, 0);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif
-#if defined(DECODE_MAGIQUEST)
- Serial.println(F("Send MagiQuest"));
- Serial.flush();
- IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address
- checkReceive(sAddress, s16BitCommand & 0x1FF); // we have 9 bit command
- delay(DELAY_AFTER_SEND);
-#endif
-
-#if defined(DECODE_BEO)
- Serial.println(F("Send Bang&Olufsen"));
- Serial.flush();
- IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, sRepeats);
-# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
- delay((RECORD_GAP_MICROS / 1000) + 1);
- IrReceiver.printIRResultRawFormatted(&Serial, true);
- uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen;
- IrReceiver.decodedIRData.rawDataPtr->rawlen = 6;
- // decode first part of frame
- IrReceiver.decode();
- IrReceiver.printIRResultShort(&Serial);
-
- // Remove trailing 6 entries for next decode
- IrReceiver.decodedIRData.rawDataPtr->rawlen = tOriginalRawlen - 6;
- for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawDataPtr->rawlen; ++i) {
- IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6];
- }
-# endif
- checkReceive(sAddress & 0x0FF, sCommand);
- delay(DELAY_AFTER_SEND);
-#endif
-
#if defined(DECODE_BOSEWAVE)
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
@@ -778,25 +1177,19 @@ void loop() {
delay(DELAY_AFTER_SEND);
#endif
- /*
- * LEGO is skipped, since it is difficult to receive because of its short marks and spaces
- */
-// Serial.println(F("Send Lego with 2 channel and with 4 command bits"));
-// Serial.flush();
-// IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, true);
-// checkReceive(sAddress, sCommand); // never has success for Lego protocol :-(
-// delay(DELAY_AFTER_SEND);
/*
* Force buffer overflow
*/
- Serial.println(F("Force buffer overflow by sending 280 marks and spaces"));
- for (unsigned int i = 0; i < 140; ++i) {
- // 400 + 400 should be received as 8/8 and sometimes as 9/7 or 7/9 if compensation by MARK_EXCESS_MICROS is optimal.
+ Serial.println(F("Force buffer overflow by sending 450 marks and spaces"));
+ for (unsigned int i = 0; i < 225; ++i) { // 225 because we send 2 entries per loop
// 210 + 540 = 750 should be received as 5/10 or 4/11 if compensation by MARK_EXCESS_MICROS is optimal.
+ // 400 + 400 should be received as 8/8 and sometimes as 9/7 or 7/9 if compensation by MARK_EXCESS_MICROS is optimal.
IrSender.mark(210); // 8 pulses at 38 kHz
IrSender.space(540); // to fill up to 750 us
}
- checkReceive(sAddress, sCommand);
+ waitForReceived();
+ IrReceiver.printIRResultRawFormatted(&Serial, true);
+ IrReceiver.resume();
delay(DELAY_AFTER_SEND);
/*
@@ -806,7 +1199,22 @@ void loop() {
sAddress += 0x0101;
sCommand += 0x11;
s16BitCommand += 0x1111;
+ sRepeats++;
+ // clip repeats at 4
+ if (sRepeats > 4) {
+ sRepeats = 4;
+ }
+ Serial.println(F("Invert toggle value for next loop"));
+ sLastSendToggleValue = !sLastSendToggleValue;
+
+ /*
+ * Test stop and start of 50 us receiver timer
+ */
+ Serial.println(F("Stop receiver"));
+ IrReceiver.stop();
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
+ Serial.println(F("Start receiver"));
+ IrReceiver.start(); // For ESP32 timerEnableReceiveInterrupt() is sufficient here, since timer is not reconfigured by another task
}
diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log
index da30c2188..4582eee2e 100644
--- a/examples/UnitTest/UnitTest.log
+++ b/examples/UnitTest/UnitTest.log
@@ -1,751 +1,1690 @@
-START ../src/UnitTest.cpp from Feb 22 2023
-Using library version 4.1.0
-Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2
+START ../src/UnitTest.cpp from Feb 20 2026
+Using library version 4.6.0
+Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Lego Power Functions, Bosewave, MagiQuest, OpenLASIR, Universal Pulse Distance Width, Hash at pin 2
+Use ReceiveCompleteCallback
+Receive buffer length is 400
Send IR signals at pin 3
If you connect debug pin 5 to ground, raw data is always printed
Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us
16000 us is the (minimum) gap, after which the start of a new IR packet is assumed
-20 us are subtracted from all marks and added to all spaces for decoding
+40 us are subtracted from all marks and added to all spaces for decoding
address=0xFFF1 command=0x76
Send NEC with 8 bit address
-Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
+Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=754900us, Duration=68000us
Send with: IrSender.sendNEC(0xF1, 0x76, );
-rawData[68]:
- -1044300
- +8950,-4400
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
+rawIRTimings[68]:
+ -754900
+ +8900,-4450
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500
+ 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 550,- 550 + 600,-1650 + 600,-1650 + 550,-1650
- + 600,- 550 + 550,- 550 + 600,- 550 + 550,- 600
- + 550,- 550 + 550,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 550,- 600 + 550,- 550 + 600,-1800
- + 450,- 500 + 600,- 550 + 550,- 550 + 600,-1650
- + 550
-Sum: 67650
+ + 600,- 550 + 600,-1650 + 650,-1600 + 600,-1600
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,- 550 + 650,-1600 + 600,-1600 + 650,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 600,- 550 + 600,-1650
+ + 650
+Duration=68000us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764800us, Duration=73450us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1055100
- +8850,-4450
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
- + 550,-1650 + 600,-1650 + 550,-1700 + 550,-1650
- + 550,- 600 + 550,-1650 + 600,-1650 + 600,- 550
- + 550,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,- 550 + 550,- 550 + 600,-1650
- + 600,- 500 + 550,- 600 + 600,- 500 + 600,-1650
- + 550
-Sum: 73150
+rawIRTimings[68]:
+ -764800
+ +8900,-4450
+ + 600,-1600 + 600,- 550 + 600,- 550 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1550
+ + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 650,- 450 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550
+ + 600,-1650 + 600,- 500 + 600,- 550 + 650,-1600
+ + 650,- 450 + 650,- 500 + 650,- 500 + 650,-1600
+ + 600
+Duration=73450us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=765250us, Duration=73450us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1055500
- +8950,-4400
- + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
- + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 450
- + 650,-1600 + 650,- 500 + 600,- 500 + 600,-1650
- + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600
+rawIRTimings[68]:
+ -765250
+ +8900,-4450
+ + 600,-1650 + 650,- 450 + 650,- 500 + 650,- 450
+ + 650,-1600 + 600,-1650 + 650,-1600 + 650,-1550
+ + 650,-1600 + 600,-1650 + 650,-1600 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ + 600,- 500 + 650,-1600 + 600,-1650 + 650,- 450
+ + 650,-1600 + 650,-1600 + 600,-1650 + 650,- 450
+ + 650,-1600 + 650,- 500 + 650,- 500 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ 650
-Sum: 73400
+Duration=73450us
+
+
+Send RC5 minimal length
+Protocol=RC5 Address=0xA, Command=0x6A, Toggle=1, Raw-Data=0xAAA, 13 bits, MSB first, Gap=765600us, Duration=23100us
+Send with: IrSender.sendRC5(0xA, 0x6A, );
+rawIRTimings[14]:
+ -765600
+ +1850,-1700
+ +1850,-1700 +1850,-1700 +1850,-1700 +1850,-1700
+ +1800,-1750 +1800
+Duration=23100us
+
-Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats
-Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
+Send RC5 maximal length
+Protocol=RC5 Address=0x1F, Command=0x3F, Toggle=1, Raw-Data=0x1FFF, 13 bits, MSB first, Gap=391600us, Duration=24200us
+Send with: IrSender.sendRC5(0x1F, 0x3F, );
+rawIRTimings[28]:
+ -391600
+ + 900,- 900
+ + 950,- 800 +1000,- 800 + 900,- 900 + 950,- 850
+ + 900,- 850 + 950,- 850 + 900,- 900 + 900,- 900
+ + 900,- 900 + 900,- 900 + 900,- 900 + 950,- 850
+ + 900
+Duration=24200us
+
+
+Send Marantz maximal length
+Protocol=Marantz Address=0x1F, Command=0x3F, Extra=0x3F, Toggle=1, Raw-Data=0x7FFFF, 19 bits, MSB first, Gap=398900us, Duration=38350us
+Send with: IrSender.sendMarantz(0x1F, 0x3F, , 0x3F);
+rawIRTimings[40]:
+ -398900
+ + 950,- 850
+ + 850,- 950 + 900,- 900 + 950,- 850 + 950,- 800
+ +1000,- 800 + 900,- 900 + 950,-4350 + 950,- 850
+ + 950,- 800 +1000,- 800 + 850,- 950 + 950,- 850
+ + 900,- 850 + 950,- 850 + 950,- 850 + 950,- 800
+ +1000,- 800 + 950,- 850 + 850
+Duration=38350us
+
+
+Send RC6 minimal length
+Protocol=RC6 Address=0x55, Command=0x55, Toggle=1, Raw-Data=0x15555, 20 bits, MSB first, Gap=744250us, Duration=23100us
+Send with: IrSender.sendRC6(0x55, 0x55, );
+rawIRTimings[26]:
+ -744250
+ +2750,- 800
+ + 550,- 800 + 500,- 400 + 500,- 450 +1400,-1250
+ +1000,- 800 + 950,- 900 + 950,- 850 +1000,- 800
+ + 950,- 850 + 950,- 900 +1000,- 800 +1000
+Duration=23100us
+
+
+Send RC6A maximal length
+Protocol=RC6A Address=0xFF, Command=0xFF, Extra=0x3FFF, Raw-Data=0x7FFFFFFF, 35 bits, MSB first, Gap=397100us, Duration=36850us
+Send with: IrSender.sendRC6A(0xFF, 0xFF, , 0x3FFF);
+rawIRTimings[72]:
+ -397100
+ +2650,- 900
+ + 550,- 400 + 400,- 500 + 500,- 850 + 500,- 850
+ +1450,- 350 + 550,- 400 + 400,- 500 + 450,- 450
+ + 500,- 400 + 550,- 400 + 400,- 500 + 450,- 450
+ + 550,- 350 + 550,- 400 + 500,- 400 + 450,- 450
+ + 500,- 400 + 500,- 450 + 400,- 500 + 450,- 450
+ + 500,- 400 + 500,- 400 + 450,- 500 + 450,- 450
+ + 500,- 400 + 550,- 350 + 450,- 500 + 450,- 450
+ + 500,- 400 + 500,- 450 + 400,- 500 + 450,- 450
+ + 450,- 450 + 550,- 350 + 500
+Duration=36850us
+
+
+Send arbitrary raw data with 1 repeat and exact timing (16 bit array format) with sendRaw()
+rawIRTimings[18]:
+ -770450
+ +8950,-4400
+ + 600,- 950 +1050,- 450 + 550,-1950 +2050,- 450
+ + 600,-2900 +3000,- 450 + 600,- 100 + 400
+Duration=29450us
+
+Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()
+Protocol=NEC Address=0x80, Command=0x45, Raw-Data=0xBA457F80, 32 bits, LSB first, Gap=713750us, Duration=68500us
Send with: IrSender.sendNEC(0x80, 0x45, );
-rawData[68]:
- -1064450
- +9050,-4450
- + 550,- 550 + 600,- 550 + 600,- 600 + 550,- 600
- + 600,- 550 + 600,- 550 + 600,- 550 + 600,-1600
- + 650,-1600 + 600,-1600 + 600,-1650 + 550,-1600
- + 600,-1600 + 600,-1600 + 600,-1600 + 650,- 500
- + 650,-1550 + 600,- 550 + 600,-1600 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,-1600 + 600,- 550
- + 650,- 500 + 650,-1550 + 600,- 550 + 600,-1600
- + 600,-1600 + 600,-1650 + 600,- 550 + 600,-1650
- + 550
-Sum: 67800
+rawIRTimings[68]:
+ -713750
+ +9100,-4350
+ + 700,- 500 + 650,- 500 + 650,- 550 + 600,- 550
+ + 650,- 550 + 700,- 450 + 650,- 500 + 650,-1600
+ + 650,-1600 + 650,-1550 + 700,-1550 + 650,-1550
+ + 700,-1500 + 700,-1550 + 700,-1550 + 650,- 500
+ + 700,-1500 + 700,- 500 + 650,-1600 + 650,- 500
+ + 650,- 500 + 700,- 450 + 650,-1600 + 650,- 550
+ + 700,- 450 + 750,-1450 + 700,- 450 + 700,-1550
+ + 650,-1600 + 700,-1550 + 650,- 500 + 700,-1500
+ + 700
+Duration=68500us
+
-Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)
-Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first
+Send NEC data with 8 bit address=0xFB04, command 0x08, 1 repeat and exact timing (16 bit array format) with sendRaw_P()
+Protocol=NEC Address=0x4, Command=0x8, Raw-Data=0xF708FB04, 32 bits, LSB first, Gap=772450us, Duration=68100us
Send with: IrSender.sendNEC(0x4, 0x8, );
-rawData[68]:
- -1061400
- +9000,-4400
- + 600,- 500 + 650,- 500 + 600,-1650 + 600,- 500
- + 650,- 500 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1650 + 600,- 500 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,- 550
+rawIRTimings[68]:
+ -772450
+ +8950,-4450
+ + 650,- 450 + 600,- 550 + 650,-1600 + 600,- 500
+ + 650,- 500 + 600,- 550 + 650,- 450 + 600,- 550
+ + 650,-1600 + 650,-1600 + 600,- 500 + 600,-1650
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 650,- 500 + 600,- 500 + 600,-1650
+ + 600,- 550 + 650,- 500 + 600,- 500 + 600,- 550
+ 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1650
+ 600
-Sum: 67900
+Duration=68100us
+
Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)
-Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
+Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=749650us, Duration=55650us
Send with: IrSender.sendOnkyo(0x102, 0x304, );
-rawData[68]:
- -1059700
- +8900,-4400
- + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 550
- + 550,- 550 + 600,- 500 + 600,-1650 + 600,- 500
- + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 500
- + 600,-1650 + 600,-1600 + 600,- 550 + 600,- 500
- + 650,- 500 + 600,- 550 + 550,- 550 + 600,- 500
+rawIRTimings[68]:
+ -749650
+ +8950,-4400
+ + 650,- 500 + 600,-1650 + 600,- 500 + 600,- 550
+ + 650,- 450 + 650,- 500 + 650,- 450 + 650,- 500
+ + 600,-1650 + 600,- 500 + 650,- 500 + 650,- 450
+ + 650,- 500 + 600,- 500 + 600,- 550 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 650,-1600 + 600,-1600 + 650,- 500 + 600,- 550
+ + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500
+ 650
-Sum: 55450
+Duration=55650us
+
Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3)
-Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
+Protocol=NEC Address=0x102, Command=0x34, Raw-Data=0xCB340102, 32 bits, LSB first, Gap=771400us, Duration=61300us
Send with: IrSender.sendNEC(0x102, 0x34, );
-rawData[68]:
- -1061500
+rawIRTimings[68]:
+ -771400
+8950,-4400
- + 600,- 500 + 550,-1700 + 600,- 500 + 650,- 500
- + 600,- 500 + 650,- 500 + 550,- 550 + 650,- 500
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1600 + 550,-1700 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,- 500 + 650,-1600 + 600,-1650
- + 550
-Sum: 61000
+ + 600,- 550 + 600,-1600 + 650,- 500 + 650,- 500
+ + 650,- 450 + 600,- 550 + 600,- 550 + 650,- 450
+ + 600,-1650 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,- 500 + 600,- 550 + 650,- 500 + 650,- 450
+ + 600,- 550 + 600,- 500 + 700,-1550 + 650,- 500
+ + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 550
+ + 600,-1600 + 600,-1650 + 600,- 550 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,-1650 + 600,-1650
+ + 650
+Duration=61300us
+
-Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=770800us, Duration=55050us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1059500
- +3450,-1700
- + 450,- 450 + 450,-1250 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 400 + 450,- 450 + 400,- 450
- + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400
- + 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450
- + 400,- 450 + 450,- 400 + 450,- 450 + 400,- 450
- + 450,-1300 + 400,-1300 + 450,- 400 + 450,-1300
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,- 400
- + 450,- 450 + 400,- 450 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400
- + 450,-1300 + 400,- 450 + 450,- 450 + 400,- 450
- + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400
- + 450,- 450 + 400,-1300 + 450,- 400 + 450,-1300
- + 450
-Sum: 54100
-
-Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance
- LSB first
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+rawIRTimings[100]:
+ -770800
+ +3550,-1650
+ + 450,- 450 + 500,-1200 + 500,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 500,- 350 + 450,- 450
+ + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 400
+ + 500,- 400 + 500,-1200 + 450,- 450 + 500,- 400
+ + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,-1250 + 450,-1300 + 450,- 450 + 400,-1300
+ + 450,- 450 + 500,- 400 + 500,- 400 + 400,- 450
+ + 500,- 400 + 450,- 450 + 500,- 350 + 500,- 450
+ + 450,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,- 400 + 450,- 400 + 550,- 350 + 500,- 400
+ + 500,- 400 + 400,-1300 + 500,- 400 + 450,-1300
+ + 500
+Duration=55050us
+
+
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400
+-LSB first
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=787500us, Duration=54050us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1076450
+rawIRTimings[100]:
+ -787500
+3450,-1700
- + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
- + 450,- 400 + 400,- 450 + 400,- 450 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,-1250 + 450,-1250 + 450,- 400 + 450,-1250
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 350
- + 500,- 400 + 400,- 450 + 450,- 350 + 500,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,-1250 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,-1200 + 500,- 400 + 450,-1300
- + 400
-Sum: 53200
+ + 550,- 350 + 450,-1200 + 550,- 350 + 500,- 350
+ + 500,- 400 + 500,- 350 + 550,- 300 + 500,- 400
+ + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350
+ + 500,- 400 + 450,-1200 + 550,- 350 + 500,- 350
+ + 550,- 350 + 500,- 350 + 500,- 350 + 500,- 350
+ + 500,-1250 + 550,-1150 + 500,- 400 + 500,-1200
+ + 550,- 300 + 500,- 400 + 500,- 350 + 500,- 350
+ + 550,- 300 + 550,- 350 + 500,- 350 + 550,- 350
+ + 500,- 350 + 550,- 350 + 500,- 350 + 550,- 300
+ + 500,-1200 + 500,- 400 + 500,- 350 + 550,- 350
+ + 450,- 400 + 550,- 300 + 500,- 350 + 550,- 350
+ + 500,- 350 + 500,-1200 + 500,- 400 + 500,-1200
+ + 500
+Duration=54050us
+
- MSB first
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+-MSB first
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=780200us, Duration=54050us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1070700
- +3400,-1700
- + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
- + 400,- 450 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,-1250 + 400,-1300 + 450,- 400 + 450,-1300
- + 400,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 550
- + 250,-1300 + 450,- 450 + 400,- 400 + 450,- 400
- + 450,- 400 + 400,- 450 + 400,- 450 + 450,- 400
- + 450,- 400 + 450,-1250 + 450,- 400 + 450,-1250
- + 450
-Sum: 53150
-
-Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first
-Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
-Send with:
- uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
- IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1650, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
-rawData[148]:
- -1076300
+rawIRTimings[100]:
+ -780200
+ +3500,-1650
+ + 550,- 350 + 500,-1200 + 500,- 350 + 550,- 350
+ + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350
+ + 550,- 350 + 550,- 300 + 500,- 350 + 550,- 350
+ + 550,- 300 + 500,-1200 + 550,- 350 + 450,- 400
+ + 500,- 350 + 550,- 300 + 550,- 350 + 500,- 350
+ + 550,-1150 + 550,-1150 + 550,- 350 + 450,-1250
+ + 500,- 350 + 500,- 400 + 550,- 300 + 500,- 350
+ + 550,- 300 + 550,- 350 + 500,- 350 + 500,- 400
+ + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350
+ + 550,-1150 + 600,- 300 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350
+ + 500,- 350 + 500,-1200 + 550,- 300 + 550,-1200
+ + 500
+Duration=54050us
+
+
+Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600
+Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=787050us, Duration=139000us
+Send on a 8 bit platform with:
+ uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
+ IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 650, 1600, 650, 500, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[148]:
+ -787050
+8850,-4400
- + 600,-1650 + 550,- 600 + 550,- 600 + 550,- 600
- + 550,- 600 + 550,-1650 + 550,- 650 + 550,- 600
- + 550,-1700 + 550,-1650 + 600,- 600 + 550,- 600
- + 550,- 600 + 500,- 650 + 550,-1650 + 600,- 600
- + 550,-1650 + 600,- 600 + 550,-1650 + 550,- 650
- + 550,- 600 + 550,-1650 + 550,-1700 + 550,- 600
- + 550,-1700 + 550,-1700 + 550,-1650 + 550,- 650
- + 550,- 600 + 550,- 600 + 550,- 600 + 550,-1700
- + 550,-1700 + 550,- 600 + 550,- 600 + 550,-1650
- + 500,- 700 + 550,-1650 + 600,- 600 + 550,-1650
- + 600,-1650 + 600,-1650 + 550,- 650 + 550,-1650
- + 550,- 600 + 550,- 600 + 550,-1700 + 550,-1700
- + 550,-1650 + 600,- 600 + 550,-1650 + 600,-1650
- + 600,- 600 + 550,-1650 + 550,-1700 + 550,-1700
- + 550,-1700 + 550,-1700 + 550,-1700 + 550,-1650
- + 550,- 650 + 550,-1650 + 550,- 650 + 550,-1700
- + 550,- 600 + 550,-1650 + 600,- 550 + 600,-1650
- + 550,-1700 + 550,- 600 + 550,-1700 + 550,- 600
- + 550
-Sum: 138200
-
-Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first
-Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first
-Send with:
- uint32_t tRawData[]={0x87654321, 0xDCBA9};
- IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
-rawData[106]:
- -1115100
+ + 600,-1650 + 600,- 550 + 650,- 500 + 650,- 550
+ + 650,- 500 + 650,-1600 + 600,- 550 + 650,- 500
+ + 650,-1600 + 650,-1600 + 650,- 500 + 650,- 550
+ + 600,- 550 + 650,- 500 + 650,-1600 + 650,- 550
+ + 600,-1650 + 600,- 550 + 650,-1600 + 650,- 500
+ + 650,- 550 + 600,-1650 + 600,-1650 + 650,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 550
+ + 650,- 550 + 650,- 500 + 600,- 550 + 650,-1650
+ + 600,-1650 + 650,- 500 + 650,- 500 + 650,-1650
+ + 600,- 550 + 650,-1600 + 650,- 500 + 650,-1600
+ + 600,-1650 + 650,-1600 + 650,- 500 + 700,-1550
+ + 650,- 550 + 600,- 550 + 650,-1600 + 600,-1650
+ + 650,-1600 + 650,- 500 + 600,-1650 + 650,-1600
+ + 700,- 450 + 650,-1600 + 650,-1650 + 600,-1650
+ + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1650
+ + 650,- 500 + 600,-1650 + 600,- 550 + 650,-1650
+ + 600,- 550 + 600,-1650 + 600,- 550 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,-1650 + 650,- 550
+ + 600
+Duration=139000us
+
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300
+Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822600us, Duration=48950us
+Send on a 8 bit platform with:
+ uint32_t tRawData[]={0x87654321, 0xDCBA9};
+ IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[108]:
+ -822600
+ 350,- 600
- + 650,- 250 + 350,- 550 + 350,- 550 + 300,- 600
- + 350,- 550 + 600,- 300 + 350,- 550 + 350,- 550
- + 600,- 300 + 600,- 300 + 350,- 550 + 350,- 550
- + 350,- 600 + 300,- 600 + 600,- 300 + 300,- 600
- + 600,- 300 + 300,- 600 + 600,- 300 + 300,- 600
- + 300,- 600 + 600,- 300 + 600,- 300 + 350,- 550
- + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 600
- + 350,- 550 + 350,- 550 + 350,- 550 + 600,- 350
- + 600,- 300 + 300,- 600 + 300,- 600 + 600,- 300
- + 300,- 600 + 600,- 300 + 300,- 600 + 600,- 300
- + 600,- 300 + 600,- 300 + 300,- 600 + 600,- 300
- + 300,- 600 + 350,- 550 + 600,- 300 + 600,- 300
- + 600,- 300 + 300,- 600 + 600,- 300 + 600
-Sum: 47550
-
-Send generic 32 bit PulseWidth 0x87654321 LSB first
-Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
-Send with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , );
-rawData[66]:
- -1088600
- + 950,- 550
- + 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250
- + 350,- 300 + 600,- 300 + 300,- 300 + 300,- 300
- + 650,- 250 + 650,- 250 + 300,- 300 + 350,- 250
- + 350,- 300 + 300,- 300 + 600,- 300 + 300,- 300
- + 600,- 300 + 350,- 250 + 600,- 300 + 350,- 250
- + 350,- 300 + 600,- 300 + 600,- 300 + 300,- 300
- + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 300
- + 300,- 300 + 300,- 300 + 350,- 250 + 650
-Sum: 24500
-
-Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first
-Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
+ + 400,- 500 + 650,- 300 + 700,- 200 + 650,- 300
+ + 650,- 200 + 400,- 550 + 700,- 250 + 700,- 150
+ + 400,- 550 + 350,- 600 + 650,- 200 + 700,- 300
+ + 600,- 300 + 650,- 250 + 400,- 500 + 650,- 300
+ + 350,- 550 + 700,- 200 + 350,- 600 + 650,- 200
+ + 750,- 200 + 400,- 550 + 350,- 550 + 650,- 300
+ + 350,- 500 + 400,- 550 + 350,- 550 + 650,- 250
+ + 650,- 300 + 700,- 250 + 650,- 200 + 400,- 550
+ + 350,- 550 + 700,- 250 + 650,- 250 + 350,- 550
+ + 650,- 300 + 350,- 550 + 650,- 250 + 400,- 500
+ + 350,- 600 + 400,- 500 + 650,- 250 + 350,- 550
+ + 700,- 250 + 700,- 200 + 400,- 500 + 400,- 550
+ + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 600
+ + 350
+Duration=48950us
+
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600
+Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=802900us, Duration=49250us
+Send on a 8 bit platform with:
+ uint32_t tRawData[]={0x87654321, 0xDCBA9};
+ IrSender.sendPulseDistanceWidthFromArray(38, 400, 550, 550, 550, 550, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[108]:
+ -802900
+ + 400,- 550
+ + 350,- 550 + 700,- 250 + 650,- 250 + 650,- 300
+ + 650,- 250 + 400,- 500 + 650,- 300 + 600,- 300
+ + 350,- 550 + 350,- 550 + 650,- 300 + 650,- 200
+ + 750,- 200 + 750,- 100 + 500,- 500 + 650,- 250
+ + 400,- 500 + 700,- 200 + 450,- 500 + 700,- 200
+ + 700,- 200 + 400,- 550 + 400,- 500 + 700,- 200
+ + 400,- 550 + 350,- 550 + 350,- 550 + 700,- 250
+ + 650,- 200 + 700,- 250 + 700,- 200 + 400,- 550
+ + 400,- 500 + 700,- 200 + 750,- 200 + 400,- 500
+ + 700,- 200 + 400,- 550 + 650,- 250 + 350,- 550
+ + 350,- 600 + 350,- 550 + 650,- 200 + 400,- 550
+ + 650,- 300 + 650,- 250 + 400,- 500 + 400,- 550
+ + 400,- 500 + 650,- 300 + 300,- 550 + 400,- 550
+ + 700
+Duration=49250us
+
+
+Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500
+Protocol=PulseDistance, Raw-Data=0x76, 7 bits, LSB first, Gap=800900us, Duration=21050us
+Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 5950, 500, 550, 1450, 1600, 450, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[18]:
+ -800900
+ +5950,- 500
+ +1550,- 450 + 550,-1450 + 600,-1400 +1600,- 400
+ + 550,-1450 + 550,-1450 + 550,-1450 + 600
+Duration=21050us
+
+
+Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275
+Protocol=PulseDistance, Raw-Data=0x3D9EAC, 23 bits, LSB first, Gap=747800us, Duration=42450us
+Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 550, 1250, 450, 1250, 1300, 400, 0x3D9EAC, 23, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[50]:
+ -747800
+ + 550,-1250
+ +1300,- 400 +1300,- 400 + 500,-1200 + 450,-1250
+ +1350,- 400 + 450,-1250 +1300,- 400 + 450,-1250
+ +1300,- 400 + 450,-1250 + 500,-1200 + 500,-1250
+ + 450,-1250 +1300,- 400 +1350,- 350 + 500,-1200
+ + 450,-1300 +1300,- 400 + 450,-1250 + 450,-1250
+ + 500,-1200 + 450,-1250 +1350,- 400 +1350
+Duration=42450us
+
+
+Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600
+Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=762850us, Duration=21150us
+Send with: IrSender.sendSony(0x11, 0x76, , 12);
+rawIRTimings[26]:
+ -762850
+ +2450,- 550
+ + 700,- 500 +1300,- 500 +1250,- 550 + 700,- 500
+ +1300,- 550 +1250,- 550 +1250,- 550 +1250,- 550
+ + 700,- 550 + 650,- 550 + 700,- 500 +1250
+Duration=21150us
+
+
+Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 - timing ratio is 1:2
+Protocol=PulseWidth, Raw-Data=0x87654321, 32 bits, LSB first, Gap=748050us, Duration=24950us
+Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1050, 500, 700, 250, 400, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[66]:
+ -748050
+ +1050,- 500
+ + 650,- 250 + 400,- 200 + 400,- 200 + 450,- 200
+ + 350,- 300 + 650,- 200 + 400,- 250 + 400,- 200
+ + 700,- 250 + 700,- 200 + 400,- 250 + 350,- 250
+ + 350,- 300 + 300,- 300 + 650,- 250 + 400,- 200
+ + 700,- 250 + 350,- 250 + 700,- 250 + 350,- 250
+ + 400,- 150 + 750,- 150 + 750,- 250 + 350,- 250
+ + 700,- 200 + 700,- 250 + 700,- 150 + 400,- 300
+ + 350,- 250 + 400,- 150 + 400,- 250 + 700
+Duration=24950us
+
+
+Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864
+Protocol=MagiQuest Address=0xFF00, Command=0x176, Raw-Data=0x6BCDFF00, 56 bits, MSB first, Gap=774150us, Duration=64900us
Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, );
-rawData[112]:
- -1089000
- + 350,- 800 + 350,- 800 + 350,- 800 + 300,- 850
- + 300,- 850 + 300,- 850 + 300,- 850 + 350,- 800
- + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550
- + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550
- + 600,- 550 + 350,- 800 + 300,- 850 + 550,- 600
- + 600,- 550 + 300,- 850 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,- 600 + 550,- 550 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,- 550 + 300,- 850
- + 300,- 850 + 350,- 800 + 300,- 850 + 300,- 850
- + 300,- 850 + 300,- 850 + 300,- 850 + 600,- 550
- + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550
- + 350,- 800 + 600,- 550 + 600,- 550 + 350,- 800
- + 300,- 850 + 300,- 850 + 300,- 850 + 600,- 600
- + 550,- 600 + 250,- 900 + 250,- 850 + 600
-Sum: 63850
+rawIRTimings[112]:
+ -774150
+ + 350,- 850 + 350,- 800 + 400,- 800 + 350,- 800
+ + 450,- 700 + 400,- 800 + 400,- 750 + 400,- 800
+ + 650,- 500 + 600,- 550 + 400,- 750 + 600,- 600
+ + 350,- 800 + 600,- 600 + 650,- 500 + 650,- 500
+ + 650,- 550 + 350,- 800 + 400,- 800 + 600,- 550
+ + 650,- 500 + 400,- 800 + 650,- 500 + 600,- 550
+ + 600,- 550 + 700,- 500 + 600,- 550 + 650,- 550
+ + 550,- 600 + 600,- 550 + 650,- 550 + 350,- 800
+ + 350,- 850 + 400,- 750 + 400,- 800 + 350,- 800
+ + 350,- 800 + 350,- 850 + 350,- 800 + 600,- 550
+ + 350,- 850 + 600,- 550 + 650,- 550 + 600,- 550
+ + 350,- 800 + 600,- 600 + 600,- 550 + 350,- 800
+ + 350,- 850 + 350,- 800 + 350,- 800 + 600,- 600
+ + 650,- 500 + 400,- 750 + 400,- 800 + 600
+Duration=64900us
+
+
+Send NEC with TinyIRSender
+Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=790250us, Duration=75050us
+Send with: IrSender.sendNEC(0xF1, 0x76, );
+rawIRTimings[68]:
+ -790250
+ +8900,-5250
+ + 600,-1950 + 600,- 650 + 600,- 600 + 600,- 650
+ + 500,-2000 + 650,-1900 + 600,-1950 + 600,-1950
+ + 650,- 600 + 550,-1950 + 650,-1900 + 650,-1900
+ + 650,- 600 + 650,- 550 + 600,- 650 + 600,- 600
+ + 650,- 550 + 650,-1900 + 600,-1950 + 600,- 650
+ + 600,-1950 + 650,-1900 + 650,-1900 + 550,- 650
+ + 600,-1950 + 650,- 550 + 650,- 600 + 600,-1900
+ + 650,- 600 + 600,- 600 + 600,- 650 + 600,-1950
+ + 600
+Duration=75050us
+
+
+Send FAST with TinyIRSender
+Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=764700us, Duration=32050us
+Send with: IrSender.sendFAST(0x76, );
+rawIRTimings[36]:
+ -764700
+ +2100,-1200
+ + 550,- 600 + 550,-1850 + 600,-1750 + 600,- 550
+ + 500,-1900 + 600,-1800 + 550,-1800 + 550,- 600
+ + 600,-1800 + 550,- 600 + 600,- 550 + 550,-1800
+ + 600,- 550 + 550,- 600 + 600,- 550 + 550,-1800
+ + 550
+Duration=32050us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first
+Protocol=Onkyo Address=0xFFF1, Command=0x7776, Raw-Data=0x7776FFF1, 32 bits, LSB first, Gap=791150us, Duration=76750us
Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, );
-rawData[68]:
- -1070700
- +8900,-4550
- + 500,-1600 + 650,- 500 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 550,-1650
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 550,-1700
- + 550,- 550 + 600,-1650 + 550,-1650 + 600,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 550,- 550
+rawIRTimings[68]:
+ -791150
+ +8900,-4450
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 650,-1550 + 650,-1600 + 600,-1650
+ + 650,-1600 + 600,-1600 + 650,-1600 + 600,-1650
+ + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 700,- 450
+ + 600,-1650 + 600,-1600 + 700,-1550 + 600,- 550
+ 600
-Sum: 76500
+Duration=76750us
+
Send Apple
-Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first
+Protocol=Apple Address=0xF1, Command=0x76, Raw-Data=0xF17687EE, 32 bits, LSB first, Gap=764350us, Duration=72350us
Send with: IrSender.sendApple(0xF1, 0x76, );
-rawData[68]:
- -1054650
- +8950,-4400
- + 600,- 550 + 550,-1650 + 650,-1600 + 600,-1600
- + 600,- 550 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550
- + 550,- 550 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 550,-1650 + 600,-1650 + 600,- 500
- + 550,-1700 + 600,-1650 + 550,-1650 + 600,- 550
- + 550,-1650 + 600,- 550 + 600,- 550 + 550,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
- + 550
-Sum: 72100
+rawIRTimings[68]:
+ -764350
+ +8900,-4450
+ + 600,- 500 + 600,-1650 + 650,-1600 + 650,-1600
+ + 600,- 500 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,-1650 + 650,-1600 + 600,-1650 + 600,- 500
+ + 650,- 500 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,- 500 + 650,-1600 + 600,-1600 + 600,- 550
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500
+ + 650,-1600 + 600,- 550 + 600,- 500 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650
+ + 600
+Duration=72350us
+
Send Panasonic
-Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+Protocol=Panasonic Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=764050us, Duration=65300us
Send with: IrSender.sendPanasonic(0xFF1, 0x76, );
-rawData[100]:
- -1054300
- +3450,-1700
- + 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400
- + 450,- 450 + 450,- 400 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,-1300 + 400,- 450 + 450,- 400
- + 450,- 450 + 400,- 450 + 450,- 400 + 450,- 450
- + 450,-1250 + 450,- 400 + 450,- 450 + 450,- 400
- + 450,-1300 + 400,-1300 + 450,-1300 + 400,-1300
- + 450,-1300 + 400,-1300 + 450,-1300 + 400,-1300
- + 450,- 450 + 450,-1250 + 500,-1250 + 450,- 400
- + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,-1300
- + 400,-1300 + 450,- 400 + 450,- 450 + 450,-1250
- + 450
-Sum: 64400
-
-Send Kaseikyo with 0x4711 as Vendor ID
-Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first
+rawIRTimings[100]:
+ -764050
+ +3500,-1700
+ + 450,- 400 + 500,-1250 + 500,- 400 + 500,- 400
+ + 450,- 450 + 500,- 350 + 500,- 400 + 500,- 350
+ + 550,- 350 + 500,- 400 + 500,- 400 + 500,- 350
+ + 450,- 450 + 500,-1250 + 450,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 400,- 450 + 500,- 400
+ + 400,-1350 + 500,- 400 + 500,- 400 + 500,- 350
+ + 550,-1200 + 500,-1250 + 450,-1250 + 500,-1250
+ + 500,-1250 + 500,-1250 + 450,-1250 + 500,-1250
+ + 500,- 400 + 500,-1250 + 500,-1250 + 500,- 350
+ + 550,-1200 + 500,-1250 + 500,-1250 + 500,- 400
+ + 450,-1250 + 500,- 400 + 500,- 400 + 450,-1300
+ + 450,-1250 + 550,- 350 + 500,- 400 + 500,-1250
+ + 500
+Duration=65300us
+
+
+Send Kaseikyo with extra=0x4711 as Vendor ID
+Protocol=Kaseikyo Address=0xFF1, Command=0x76, Extra=0x4711, Raw-Data=0x9A76FF13, 48 bits, LSB first, Gap=784400us, Duration=70450us
Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711);
-rawData[100]:
- -1074550
- +3400,-1750
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 450
- + 400,-1300 + 450,- 400 + 450,- 450 + 450,- 400
- + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450
- + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 450
- + 400,-1300 + 450,-1300 + 400,- 450 + 450,- 400
- + 450,-1300 + 450,- 400 + 450,- 450 + 400,- 450
- + 450,-1250 + 400,-1350 + 450,-1300 + 400,-1350
- + 400,-1300 + 400,-1300 + 450,-1300 + 450,-1250
- + 450,- 450 + 400,-1300 + 450,-1300 + 400,- 450
- + 450,-1250 + 450,-1300 + 400,-1300 + 450,- 400
- + 450,- 450 + 450,-1250 + 450,- 400 + 450,-1300
- + 450,-1250 + 450,- 400 + 450,- 450 + 450,-1250
- + 450
-Sum: 69500
+rawIRTimings[100]:
+ -784400
+ +3450,-1700
+ + 550,-1200 + 500,- 400 + 450,- 450 + 500,- 350
+ + 500,-1250 + 450,- 450 + 450,- 450 + 500,- 400
+ + 500,-1200 + 500,-1250 + 500,-1250 + 500,- 400
+ + 450,- 400 + 550,- 350 + 500,-1250 + 500,- 400
+ + 500,-1200 + 450,-1300 + 500,- 400 + 500,- 400
+ + 450,-1250 + 500,- 400 + 500,- 400 + 450,- 450
+ + 450,-1250 + 500,-1250 + 500,-1250 + 500,-1250
+ + 450,-1300 + 500,-1200 + 500,-1250 + 500,-1250
+ + 500,- 400 + 500,-1250 + 450,-1250 + 500,- 400
+ + 500,-1250 + 500,-1250 + 450,-1250 + 500,- 400
+ + 550,- 350 + 450,-1300 + 500,- 400 + 500,-1250
+ + 450,-1250 + 550,- 350 + 500,- 400 + 500,-1250
+ + 500
+Duration=70450us
+
Send Kaseikyo_Denon variant
-Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+Protocol=Kaseikyo_Denon Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=784650us, Duration=68700us
Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, );
-rawData[100]:
- -1067700
- +3400,-1750
- + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 400
- + 450,-1300 + 450,- 400 + 450,-1300 + 400,- 450
- + 450,- 400 + 450,-1300 + 450,- 400 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,- 400 + 450,- 450
- + 400,- 450 + 450,- 400 + 450,- 450 + 400,- 450
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,-1300 + 400,-1300
- + 450,-1300 + 400,-1300 + 450,-1250 + 450,-1300
- + 450,- 400 + 450,-1300 + 400,-1300 + 450,- 400
- + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450
- + 450,-1250 + 450,- 450 + 400,- 450 + 450,-1300
- + 400,-1300 + 450,- 400 + 450,- 450 + 450,-1250
- + 450
-Sum: 67700
-
-Send Denon
-Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first
+rawIRTimings[100]:
+ -784650
+ +3550,-1650
+ + 500,- 400 + 500,- 400 + 450,-1250 + 500,- 400
+ + 450,-1300 + 450,- 450 + 500,-1200 + 500,- 400
+ + 450,- 450 + 450,-1250 + 500,- 400 + 450,- 450
+ + 500,-1250 + 500,-1250 + 500,- 400 + 500,- 350
+ + 500,- 400 + 500,- 400 + 500,- 400 + 500,- 350
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,-1250 + 450,-1250 + 450,-1300 + 500,-1250
+ + 500,-1250 + 500,-1250 + 450,-1250 + 550,-1200
+ + 500,- 400 + 500,-1250 + 500,-1250 + 500,- 400
+ + 450,-1250 + 500,-1250 + 450,-1300 + 450,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250
+ + 500
+Duration=68700us
+
+
+Send Denon with 2 autorepeats after 45 ms
+Protocol=Denon Address=0x11, Command=0x76, Raw-Data=0xED1, 15 bits, LSB first, Gap=784950us, Duration=23450us
Send with: IrSender.sendDenon(0x11, 0x76, );
-rawData[32]:
- -1073050
- + 250,-1850 + 250,- 750 + 250,- 800 + 250,- 800
- + 250,-1800 + 250,- 800 + 250,-1800 + 250,-1850
- + 250,- 750 + 300,-1800 + 250,-1800 + 300,-1800
- + 250,- 750 + 300,- 750 + 300,- 750 + 250
-Sum: 23050
-
-Send Denon/Sharp variant
-Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first
+rawIRTimings[32]:
+ -784950
+ + 350,-1750 + 350,- 700 + 300,- 800 + 300,- 750
+ + 300,-1750 + 350,- 750 + 300,-1750 + 350,-1750
+ + 300,- 750 + 350,-1750 + 350,-1750 + 300,-1800
+ + 300,- 750 + 300,- 750 + 300,- 750 + 350
+Duration=23450us
+
+
+Send Denon/Sharp variant with 2 autorepeat5 after 45 ms
+Protocol=Sharp Address=0x11, Command=0x76, Raw-Data=0x2ED1, 15 bits, LSB first, Gap=728000us, Duration=24400us
Send with: IrSender.sendSharp(0x11, 0x76, );
-rawData[32]:
- -1018750
- + 300,-1750 + 300,- 750 + 250,- 800 + 250,- 800
- + 250,-1800 + 250,- 800 + 250,-1800 + 300,-1800
- + 250,- 800 + 250,-1800 + 300,-1750 + 300,-1800
- + 250,- 800 + 250,- 750 + 300,-1800 + 250
-Sum: 24100
+rawIRTimings[32]:
+ -728000
+ + 350,-1750 + 300,- 750 + 300,- 750 + 300,- 750
+ + 350,-1750 + 300,- 750 + 300,-1800 + 350,-1700
+ + 300,- 750 + 350,-1750 + 350,-1750 + 300,-1800
+ + 350,- 700 + 350,-1700 + 300,- 800 + 300
+Duration=24400us
+
Send Sony/SIRCS with 7 command and 5 address bits
-Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
-Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
-rawData[26]:
- -1020950
- +2400,- 650
- + 550,- 600 +1200,- 550 +1250,- 550 + 650,- 550
- +1250,- 550 +1250,- 600 +1200,- 550 +1200,- 600
- + 650,- 550 + 650,- 550 + 650,- 550 +1200
-Sum: 20950
+Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=727550us, Duration=21250us
+Send with: IrSender.sendSony(0x11, 0x76, , 12);
+rawIRTimings[26]:
+ -727550
+ +2500,- 550
+ + 650,- 550 +1250,- 550 +1250,- 550 + 700,- 500
+ +1250,- 600 +1250,- 550 +1250,- 550 +1300,- 500
+ + 650,- 550 + 700,- 550 + 650,- 550 +1300
+Duration=21250us
+
Send Sony/SIRCS with 7 command and 8 address bits
-Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first
-Send with: IrSender.sendSony(0xF1, 0x76, 2, 15);
-rawData[32]:
- -1032550
+Protocol=Sony Address=0xF1, Command=0x76, Raw-Data=0x78F6, 15 bits, LSB first, Gap=744950us, Duration=26650us
+Send with: IrSender.sendSony(0xF1, 0x76, , 15);
+rawIRTimings[32]:
+ -744950
+2400,- 600
- + 600,- 600 +1200,- 600 +1200,- 550 + 650,- 550
- +1200,- 600 +1200,- 650 +1200,- 550 +1200,- 600
- + 650,- 550 + 650,- 550 + 650,- 550 +1200,- 600
- +1200,- 600 +1250,- 600 +1200
-Sum: 26400
-
-Send Sony/SIRCS with 7 command and 13 address bits
-Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first
-Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20);
-rawData[42]:
- -1036350
- +2300,- 650
- + 600,- 600 +1200,- 550 +1250,- 550 + 650,- 600
- +1200,- 550 +1250,- 550 +1200,- 600 +1250,- 600
- + 600,- 600 + 600,- 600 + 600,- 550 +1200,- 600
- +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 600
- +1200,- 550 +1200,- 600 +1250,- 600 +1200
-Sum: 35350
-
-Send Samsung 8 bit command
-Protocol=Samsung Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+ + 700,- 500 +1250,- 600 +1300,- 500 + 700,- 500
+ +1250,- 550 +1300,- 550 +1250,- 550 +1250,- 550
+ + 700,- 550 + 600,- 600 + 650,- 550 +1250,- 600
+ +1250,- 550 +1250,- 550 +1250
+Duration=26650us
+
+
+Send Sony/SIRCS with 7 command and 13 address bits and no repeats
+Protocol=Sony Address=0x1FF1, Command=0x76, Raw-Data=0xFF8F6, 20 bits, LSB first, Gap=749650us, Duration=35650us
+Send with: IrSender.sendSony(0x1FF1, 0x76, , 20);
+rawIRTimings[42]:
+ -749650
+ +2450,- 550
+ + 650,- 550 +1250,- 550 +1250,- 550 + 700,- 550
+ +1300,- 500 +1250,- 550 +1300,- 500 +1250,- 550
+ + 700,- 550 + 650,- 550 + 700,- 500 +1250,- 550
+ +1250,- 550 +1250,- 550 +1250,- 600 +1250,- 550
+ +1250,- 550 +1250,- 550 +1250,- 550 +1300
+Duration=35650us
+
+
+Send Samsung 8 bit command and 8 bit address
+Protocol=Samsung Address=0xF1, Command=0x76, Raw-Data=0x8976F1F1, 32 bits, LSB first, Gap=753500us, Duration=65700us
+Send with: IrSender.sendSamsung(0xF1, 0x76, );
+rawIRTimings[68]:
+ -753500
+ +4500,-4400
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600
+ + 650,-1600 + 600,- 550 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1600
+ + 650
+Duration=65700us
+
+
+Send Samsung 8 bit command and 16 bit address
+Protocol=Samsung Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=766950us, Duration=68950us
Send with: IrSender.sendSamsung(0xFFF1, 0x76, );
-rawData[68]:
- -1039650
- +4400,-4450
- + 550,-1700 + 550,- 550 + 600,- 550 + 550,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 550,-1650
- + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,- 550 + 550,-1650 + 600,-1650 + 600,- 550
- + 550,-1650 + 600,-1650 + 550,-1700 + 550,- 550
- + 600,-1650 + 550,- 550 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,- 550 + 550,- 550 + 600,-1650
+rawIRTimings[68]:
+ -766950
+ +4450,-4450
+ + 650,-1600 + 650,- 500 + 600,- 500 + 600,- 500
+ + 650,-1600 + 600,-1650 + 600,-1650 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 650,-1600 + 600,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 650,-1550 + 650,- 500
+ + 600,-1650 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,- 500 + 650,- 500 + 650,- 450 + 650,-1600
+ 600
-Sum: 68750
+Duration=68950us
+
-Send Samsung 16 bit command
-Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
+Send Samsung 16 bit command and address
+Protocol=Samsung Address=0xFFF1, Command=0x9876, Raw-Data=0x9876FFF1, 32 bits, LSB first, Gap=766800us, Duration=69050us
Send with: IrSender.sendSamsung(0xFFF1, 0x9876, );
-rawData[68]:
- -1056350
- +4400,-4400
- + 600,-1650 + 550,- 550 + 600,- 550 + 550,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1600
- + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,- 500 + 550,-1700 + 600,-1650 + 550,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550
- + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
- + 550,-1650 + 600,- 550 + 600,- 550 + 550,-1650
+rawIRTimings[68]:
+ -766800
+ +4500,-4400
+ + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
+ + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1600
+ + 600,-1650 + 650,-1600 + 650,-1600 + 600,-1650
+ + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,-1600 + 700,- 450
+ + 600,- 550 + 600,- 500 + 700,- 450 + 650,-1600
+ + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650
+ 600
-Sum: 68650
+Duration=69050us
+
Send Samsung48 16 bit command
-Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first
+Protocol=Samsung48 Address=0xFFF1, Command=0x9876, Raw-Data=0x6798, 48 bits, LSB first, Gap=766300us, Duration=96000us
Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, );
-rawData[100]:
- -1056750
- +4450,-4450
- + 600,-1650 + 600,- 500 + 600,- 550 + 550,- 550
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
- + 550,-1650 + 550,-1700 + 550,-1700 + 550,-1650
- + 600,- 550 + 550,-1700 + 550,-1650 + 600,- 550
- + 550,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650
- + 550,- 550 + 600,- 550 + 550,- 550 + 550,-1700
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
- + 550,-1650 + 600,- 550 + 550,- 550 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550
- + 550,- 550 + 600,-1650 + 550,-1650 + 600,- 550
- + 550
-Sum: 95650
+rawIRTimings[100]:
+ -766300
+ +4500,-4400
+ + 650,-1600 + 600,- 500 + 650,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600
+ + 600,-1650 + 600,-1650 + 650,-1600 + 600,-1600
+ + 650,- 500 + 600,-1650 + 650,-1600 + 600,- 500
+ + 600,-1650 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,-1600 + 650,- 500 + 650,- 450 + 650,-1600
+ + 650,- 500 + 650,- 450 + 650,- 500 + 600,-1650
+ + 650,- 500 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,- 500 + 600,- 550 + 650,-1600
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600
+Duration=96000us
+
Send RC5
-Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first
+Protocol=RC5 Address=0x11, Command=0x36, Raw-Data=0x1476, 13 bits, MSB first, Gap=782400us, Duration=23300us
Send with: IrSender.sendRC5(0x11, 0x36, );
-rawData[20]:
- -1073300
- + 900,- 900
- +1750,-1800 +1750,- 900 + 900,- 850 + 900,-1750
- + 900,- 900 + 900,- 850 +1800,-1800 + 900,- 850
- +1800
-Sum: 23100
+rawIRTimings[20]:
+ -782400
+ + 950,- 850
+ +1850,-1700 +1850,- 850 + 900,- 850 +1000,-1700
+ + 950,- 850 + 900,- 850 +1850,-1750 + 900,- 850
+ +1900
+Duration=23300us
+
Send RC5X with 7.th MSB of command set
-Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first
+Protocol=RC5 Address=0x11, Command=0x76, Toggle=1, Raw-Data=0xC76, 13 bits, MSB first, Gap=742050us, Duration=23250us
Send with: IrSender.sendRC5(0x11, 0x76, );
-rawData[20]:
- -1031250
+rawIRTimings[20]:
+ -742050
+1800,-1750
- + 850,- 900 +1800,- 850 + 900,- 900 + 900,-1750
- + 900,- 900 + 850,- 900 +1750,-1800 + 900,- 850
- +1800
-Sum: 23050
+ + 950,- 800 +1900,- 800 + 900,- 850 +1000,-1700
+ +1000,- 800 + 900,- 850 +1900,-1650 +1000,- 800
+ +1900
+Duration=23250us
+
+
+Send Marantz with RC5 and extra=0x9
+Protocol=Marantz Address=0x11, Command=0x36, Extra=0x9, Raw-Data=0x51D89, 19 bits, MSB first, Gap=742600us, Duration=38400us
+Send with: IrSender.sendMarantz(0x11, 0x36, , 0x9);
+rawIRTimings[30]:
+ -742600
+ + 900,- 850
+ +1850,-1750 +1800,- 850 + 900,- 850 +1000,-1700
+ +1000,-4350 + 950,- 850 +1800,-1750 + 950,- 800
+ +1850,- 850 + 900,- 900 + 900,-1750 +1850,- 800
+ +1000,-1700 +1000
+Duration=38400us
+
+
+Send Marantz with RC5A and extra=0x9
+Protocol=Marantz Address=0x11, Command=0x76, Extra=0x9, Toggle=1, Raw-Data=0x31D89, 19 bits, MSB first, Gap=748550us, Duration=38400us
+Send with: IrSender.sendMarantz(0x11, 0x76, , 0x9);
+rawIRTimings[30]:
+ -748550
+ +1800,-1800
+ + 950,- 850 +1800,- 800 +1000,- 800 +1000,-1700
+ + 950,-4400 + 900,- 850 +1850,-1750 + 950,- 850
+ +1800,- 850 + 950,- 850 + 950,-1700 +1800,- 850
+ +1000,-1750 + 900
+Duration=38400us
+
Send RC6
-Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first
+Protocol=RC6 Address=0xF1, Command=0x76, Raw-Data=0xF176, 20 bits, MSB first, Gap=746200us, Duration=23600us
Send with: IrSender.sendRC6(0xF1, 0x76, );
-rawData[36]:
- -1028550
- +2650,- 900
- + 450,- 900 + 450,- 450 + 450,- 450 + 450,- 850
- +1350,- 450 + 450,- 450 + 450,- 450 + 450,- 900
- + 450,- 450 + 450,- 450 + 900,- 900 + 900,- 450
- + 450,- 450 + 450,- 900 + 850,- 450 + 450,- 900
- + 450
-Sum: 23250
+rawIRTimings[36]:
+ -746200
+ +2700,- 800
+ + 600,- 750 + 550,- 400 + 550,- 350 + 500,- 850
+ +1400,- 400 + 550,- 350 + 550,- 400 + 500,- 850
+ + 500,- 400 + 550,- 350 + 950,- 900 + 950,- 400
+ + 550,- 400 + 500,- 850 +1000,- 350 + 550,- 800
+ + 550
+Duration=23600us
+
+
+Send RC6A with 14 bit and extra=0x2711
+Protocol=RC6A Address=0xF1, Command=0x76, Extra=0x2711, Toggle=1, Raw-Data=0xA711F176, 35 bits, MSB first, Gap=749050us, Duration=37450us
+Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711);
+rawIRTimings[58]:
+ -749050
+ +2700,- 850
+ + 500,- 400 + 550,- 350 + 500,- 850 +1450,-1300
+ +1000,- 850 + 500,- 400 +1000,- 400 + 500,- 450
+ + 500,- 800 + 500,- 400 + 500,- 450 + 950,- 850
+ + 500,- 450 + 500,- 400 +1000,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 550,- 850 + 500,- 400
+ + 500,- 400 +1050,- 800 +1000,- 400 + 500,- 400
+ + 500,- 850 +1000,- 400 + 500,- 850 + 550
+Duration=37450us
+
+
+Send MagiQuest, WandId=0x6BCDFFF1
+Protocol=MagiQuest Address=0xFFF1, Command=0x76, Raw-Data=0x6BCDFFF1, 56 bits, MSB first, Gap=763750us, Duration=65050us
+Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, );
+rawIRTimings[112]:
+ -763750
+ + 350,- 800 + 400,- 800 + 350,- 800 + 400,- 750
+ + 400,- 800 + 350,- 800 + 350,- 850 + 350,- 850
+ + 600,- 600 + 650,- 500 + 350,- 800 + 600,- 600
+ + 350,- 800 + 650,- 500 + 650,- 550 + 650,- 500
+ + 650,- 550 + 350,- 800 + 400,- 750 + 650,- 550
+ + 600,- 550 + 400,- 800 + 600,- 550 + 650,- 500
+ + 600,- 600 + 650,- 500 + 650,- 500 + 650,- 550
+ + 600,- 550 + 650,- 550 + 600,- 550 + 600,- 550
+ + 650,- 500 + 600,- 600 + 600,- 550 + 350,- 800
+ + 400,- 800 + 400,- 750 + 650,- 550 + 350,- 800
+ + 350,- 850 + 650,- 500 + 650,- 550 + 600,- 550
+ + 350,- 800 + 650,- 550 + 600,- 550 + 350,- 850
+ + 350,- 800 + 350,- 850 + 650,- 500 + 650,- 550
+ + 350,- 800 + 650,- 500 + 650,- 550 + 650
+Duration=65050us
+
+
+Send OpenLASIR mode fire and color orange, detected as ONKYO
+Protocol=Onkyo Address=0xF1, Command=0xC076, Raw-Data=0xC0760EF1, 32 bits, LSB first, Gap=792950us, Duration=66750us
+Send with: IrSender.sendOnkyo(0xF1, 0xC076, );
+rawIRTimings[68]:
+ -792950
+ +8950,-4400
+ + 600,-1650 + 600,- 500 + 600,- 550 + 650,- 500
+ + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,-1600 + 650,-1600 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,- 550 + 600,-1600 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500
+ + 650,- 500 + 650,- 500 + 600,-1600 + 600,-1650
+ + 600
+Duration=66750us
+
+
+Send Lego with 2 channel and with 4 command bits
+Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169, 16 bits, MSB first, Gap=767200us, Duration=10250us
+Send with: IrSender.sendLego(0x1, 0x16, );
+rawIRTimings[36]:
+ -767200
+ + 250,- 950
+ + 250,- 500 + 250,- 150 + 200,- 300 + 200,- 500
+ + 250,- 150 + 200,- 600 + 250,- 500 + 200,- 150
+ + 300,- 500 + 200,- 200 + 250,- 200 + 200,- 300
+ + 250,- 450 + 250,- 150 + 200,- 300 + 250,- 150
+ + 250
+Duration=10250us
+
+
+Send 16 bit Bang&Olufsen - requires originally 455 kHz
+- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
+rawIRTimings[44]:
+ -749450
+ + 250,-2850
+ + 300,-2850 + 250,-12750 + 250,-2850 + 250,-9050
+ + 250,-5950 + 250,-5950 + 300,-5950 + 250,-2850
+ + 250,-5950 + 300,-5900 + 300,-9000 + 250,-2900
+ + 250,-9050 + 250,-5950 + 300,-5900 + 300,-2850
+ + 300,-9000 + 250,-5950 + 250,-2850 + 300,-12100
+ + 300
+Duration=134400us
+
+- Now try to decode the first 6 entries, which results in rawData 0x0
+Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=749450us, Duration=6500us
+
+- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
+Protocol=Bang&Olufsen Address=0xF1, Command=0x76, Raw-Data=0xF176, 16 bits, MSB first, Gap=12750us, Duration=115150us
+Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, );
+rawIRTimings[38]:
+ -12750
+ + 250,-2850
+ + 250,-9050 + 250,-5950 + 250,-5950 + 300,-5950
+ + 250,-2850 + 250,-5950 + 300,-5900 + 300,-9000
+ + 250,-2900 + 250,-9050 + 250,-5950 + 300,-5900
+ + 300,-2850 + 300,-9000 + 250,-5950 + 250,-2850
+ + 300,-12100 + 300
+Duration=115150us
+
+
+Send next protocols with IrSender.write
Send JVC
-Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first
+Protocol=JVC Address=0xF1, Command=0x76, Raw-Data=0x76F1, 16 bits, LSB first, Gap=805500us, Duration=40700us
Send with: IrSender.sendJVC(0xF1, 0x76, );
-rawData[36]:
- -1037050
- +8400,-4150
- + 500,-1600 + 550,- 500 + 500,- 550 + 550,- 500
- + 550,-1550 + 550,-1550 + 500,-1600 + 550,-1550
- + 550,- 500 + 550,-1550 + 550,-1550 + 500,- 550
- + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
- + 550
-Sum: 40400
+rawIRTimings[36]:
+ -805500
+ +8450,-4100
+ + 650,-1500 + 600,- 450 + 600,- 450 + 600,- 500
+ + 550,-1550 + 600,-1500 + 600,-1500 + 550,-1600
+ + 550,- 500 + 600,-1500 + 600,-1500 + 600,- 500
+ + 550,-1550 + 600,-1500 + 600,-1500 + 600,- 500
+ + 600
+Duration=40700us
-Send Samsung
-Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
-Send with: IrSender.sendSamsung(0xFFF1, 0x9876, );
-rawData[68]:
- -1036350
- +4450,-4400
- + 550,-1700 + 600,- 550 + 550,- 550 + 600,- 550
- + 550,-1650 + 600,-1650 + 600,-1650 + 550,-1650
- + 550,-1700 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
- + 550,- 550 + 600,-1650 + 550,-1700 + 550,- 550
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550
- + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
- + 550,-1650 + 600,- 550 + 600,- 500 + 600,-1700
- + 550
-Sum: 68750
Send LG
-Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first
+Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745900us, Duration=59900us
Send with: IrSender.sendLG(0xF1, 0x9876, );
-rawData[60]:
- -1054900
- +9000,-4150
- + 450,-1600 + 500,-1550 + 500,-1550 + 500,-1600
- + 500,- 550 + 500,- 550 + 500,- 550 + 500,-1550
- + 500,-1600 + 500,- 550 + 500,- 550 + 450,-1600
- + 500,-1600 + 500,- 550 + 500,- 550 + 500,- 550
- + 500,- 550 + 500,-1550 + 500,-1550 + 550,-1550
- + 500,- 550 + 500,-1550 + 500,-1600 + 500,- 550
- + 500,-1550 + 500,-1550 + 500,-1600 + 500,- 550
- + 500
-Sum: 59350
+rawIRTimings[60]:
+ -745900
+ +8350,-4150
+ + 550,-1550 + 600,-1550 + 550,-1550 + 550,-1550
+ + 600,- 550 + 500,- 550 + 550,- 550 + 550,-1550
+ + 550,-1550 + 550,- 550 + 550,- 550 + 550,-1550
+ + 550,-1550 + 550,- 550 + 550,- 550 + 550,- 550
+ + 550,- 550 + 550,-1550 + 550,-1550 + 550,-1550
+ + 550,- 550 + 550,-1550 + 550,-1550 + 550,- 550
+ + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 550
+ + 550
+Duration=59900us
-Send MagiQuest
-Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first
-Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, );
-rawData[112]:
- -1049950
- + 250,- 850 + 250,- 900 + 250,- 900 + 250,- 900
- + 250,- 900 + 300,- 850 + 250,- 900 + 250,- 900
- + 600,- 550 + 600,- 550 + 300,- 850 + 550,- 600
- + 250,- 900 + 550,- 600 + 550,- 600 + 550,- 600
- + 550,- 600 + 300,- 850 + 250,- 900 + 550,- 600
- + 550,- 600 + 300,- 850 + 550,- 600 + 550,- 600
- + 550,- 600 + 550,- 600 + 550,- 600 + 550,- 600
- + 550,- 600 + 550,- 600 + 550,- 600 + 550,- 600
- + 550,- 600 + 550,- 600 + 600,- 550 + 300,- 900
- + 250,- 900 + 250,- 900 + 550,- 550 + 300,- 850
- + 250,- 900 + 550,- 600 + 550,- 600 + 550,- 600
- + 300,- 850 + 550,- 600 + 550,- 600 + 250,- 900
- + 300,- 850 + 300,- 850 + 600,- 550 + 550,- 600
- + 300,- 850 + 550,- 600 + 550,- 600 + 550
-Sum: 63750
-
-Send Bang&Olufsen
-Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first
-Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, );
-rawData[44]:
- -1078450
- + 150,-2850
- + 200,-2900 + 200,-15300 + 200,-2900 + 200,-9100
- + 250,-5950 + 250,-5950 + 250,-5950 + 200,-2900
- + 200,-6000 + 200,-6000 + 200,-9100 + 200,-2900
- + 200,-9100 + 250,-5950 + 250,-5950 + 250,-2850
- + 200,-9100 + 250,-5950 + 250,-2850 + 200,-12200
- + 200
-Sum: 136500
Send Bosewave with no address and 8 command bits
-Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+Protocol=BoseWave Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=762400us, Duration=27150us
Send with: IrSender.sendBoseWave(0x0, 0x76, );
-rawData[36]:
- -1044750
- +1050,-1450
- + 550,- 450 + 550,-1400 + 550,-1450 + 550,- 450
- + 500,-1450 + 550,-1450 + 500,-1450 + 550,- 450
- + 550,-1400 + 550,- 450 + 550,- 450 + 550,-1450
- + 500,- 500 + 500,- 450 + 550,- 450 + 550,-1450
- + 500
-Sum: 26750
+rawIRTimings[36]:
+ -762400
+ +1100,-1400
+ + 600,- 450 + 550,-1400 + 600,-1400 + 600,- 450
+ + 550,-1400 + 600,-1400 + 600,-1400 + 600,- 450
+ + 550,-1400 + 600,- 450 + 550,- 400 + 650,-1350
+ + 600,- 450 + 550,- 450 + 550,- 450 + 600,-1400
+ + 600
+Duration=27150us
+
Send FAST
-Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
-Send with: IrSender.sendFAST(0x0, 0x76, );
-rawData[36]:
- -1036750
- +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
-
-Force buffer overflow by sending 280 marks and spaces
-Overflow
-Try to increase the "RAW_BUFFER_LENGTH" value of 150 in ../src/UnitTest.cpp
-rawData[150]:
- -1040000
- + 250,- 500
- + 200,- 600 + 200,- 550 + 200,- 500 + 200,- 550
- + 200,- 550 + 250,- 500 + 250,- 550 + 200,- 550
- + 250,- 500 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,-1300
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 250,- 500 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 500 + 250,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 500 + 250,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550
- + 200,- 550 + 250,- 500 + 200,- 550 + 200,- 550
- + 200,- 550 + 200,- 500 + 250,- 550 + 200,- 500
- + 250,- 550 + 200,- 550 + 250,- 500 + 200,- 550
- + 200,- 550 + 200
-Sum: 56500
-ERROR: Unknown protocol
-
-
-address=0xF2 command=0x87
+Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=746700us, Duration=29250us
+Send with: IrSender.sendFAST(0x76, );
+rawIRTimings[36]:
+ -746700
+ +2200,-1000
+ + 600,- 450 + 600,-1550 + 550,-1550 + 600,- 450
+ + 600,-1500 + 600,-1550 + 550,-1550 + 550,- 500
+ + 600,-1500 + 600,- 500 + 550,- 500 + 600,-1550
+ + 550,- 500 + 600,- 450 + 600,- 500 + 550,-1550
+ + 600
+Duration=29250us
-Send NEC with 8 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+
+Force buffer overflow by sending 450 marks and spaces
+rawIRTimings[400]:
+ -745550
+ + 250,- 550
+ + 250,- 500 + 300,- 500 + 300,- 450 + 300,- 450
+ + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500
+ + 300,- 450 + 250,- 500 + 300,- 500 + 250,- 500
+ + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550
+ + 200,- 550 + 200,- 550 + 200,- 550 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 300,- 450
+ + 300,- 450 + 300,- 500 + 200,- 550 + 200,- 550
+ + 300,- 500 + 200,- 550 + 300,- 500 + 250,- 500
+ + 300,- 500 + 200,- 550 + 200,- 550 + 250,- 500
+ + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 500
+ + 300,- 450 + 250,- 500 + 300,- 500 + 250,- 500
+ + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 500
+ + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500
+ + 200,- 550 + 200,- 550 + 300,- 500 + 250,- 500
+ + 200,- 600 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 500 + 300,- 500 + 200,- 550
+ + 200,- 550 + 250,- 550 + 250,- 500 + 200,- 550
+ + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500
+ + 250,- 500 + 250,- 550 + 200,- 550 + 200,- 550
+ + 250,- 550 + 250,- 500 + 250,- 500 + 200,- 600
+ + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500
+ + 300,- 500 + 250,- 500 + 300,- 450 + 250,- 500
+ + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500
+ + 200,- 550 + 300,- 500 + 200,- 550 + 250,- 500
+ + 300,- 500 + 300,- 450 + 300,- 450 + 300,- 500
+ + 300,- 450 + 200,- 550 + 300,- 500 + 250,- 500
+ + 250,- 500 + 250,- 550 + 250,- 500 + 300,- 450
+ + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 300,- 450
+ + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500
+ + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 500 + 250,- 550 + 250,- 500 + 300,- 500
+ + 250,- 500 + 250,- 500 + 250,- 550 + 200,- 550
+ + 250,- 500 + 250,- 550 + 250,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 550
+ + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500
+ + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550
+ + 200,- 600 + 200,- 500 + 250,- 550 + 200,- 550
+ + 250,- 550 + 200,- 550 + 250,- 550 + 200,- 550
+ + 200,- 550 + 250,- 500 + 250,- 550 + 200,- 600
+ + 200,- 550 + 200,- 550 + 250,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 600
+ + 200,- 550 + 200,- 550 + 200,- 550 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 550
+ + 250,- 550 + 200,- 550 + 200
+Duration=152950us
+
+Invert toggle value for next loop
+Stop receiver
+Start receiver
+
+address=0xF2 command=0x87 repeats=1
+
+Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=915400us, Duration=67850us
Send with: IrSender.sendNEC(0xF2, 0x87, );
-rawData[68]:
- -3276750
- +8850,-4500
- + 550,- 500 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1600 + 600,- 550 + 600,-1650 + 550,-1650
- + 600,- 550 + 550,- 550 + 600,- 550 + 550,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,- 550
- + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
- + 600,- 500 + 550,- 600 + 550,- 550 + 600,-1650
- + 550,-1700 + 550,-1650 + 600,-1650 + 600,- 500
+rawIRTimings[68]:
+ -915400
+ +8900,-4450
+ + 600,- 500 + 600,-1650 + 700,- 450 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ + 600,-1650 + 650,- 500 + 600,-1650 + 600,-1600
+ + 650,- 500 + 600,- 550 + 650,- 450 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600
+ + 650,- 450 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ 600
-Sum: 67600
+Duration=67850us
+
+
+Protocol=NEC2 Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Repeat, Gap=69250us, Duration=67900us
+Send with: IrSender.sendNEC2(0xF2, 0x87, );
+rawIRTimings[68]:
+ -69250
+ +8900,-4450
+ + 600,- 500 + 650,-1600 + 700,- 450 + 600,- 500
+ + 600,-1650 + 600,-1650 + 650,-1600 + 650,-1600
+ + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1650
+ + 650,- 450 + 600,- 550 + 650,- 450 + 600,- 550
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650
+Duration=67900us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=765500us, Duration=67850us
Send with: IrSender.sendNEC(0xF2, 0x87, );
-rawData[68]:
- -998700
- +8900,-4400
- + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
+rawIRTimings[68]:
+ -765500
+ +8950,-4350
+ + 600,- 550 + 700,-1550 + 650,- 450 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600
+ + 600,-1650 + 650,- 500 + 600,-1650 + 650,-1600
+ + 600,- 500 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1650 + 650,-1550 + 650,-1600 + 650,- 500
+ 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
+ + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500
+ 600
-Sum: 67650
+Duration=67850us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=745150us, Duration=67900us
Send with: IrSender.sendNEC(0xF2, 0x87, );
-rawData[68]:
- -1055100
- +8950,-4400
- + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500
+rawIRTimings[68]:
+ -745150
+ +8900,-4450
+ + 600,- 500 + 650,-1600 + 600,- 550 + 600,- 500
+ 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
- + 650,-1600 + 650,- 500 + 650,-1600 + 600,-1600
- + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500
- + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,-1600 + 650,- 500 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500
+ + 650,-1600 + 600,-1650 + 600,-1650 + 650,- 450
+ + 600,- 550 + 650,- 500 + 600,- 500 + 600,-1650
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+ + 600,-1650 + 650,-1550 + 600,-1650 + 650,- 500
+ + 600
+
+
+Send NEC with TinyIRSender
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=744800us, Duration=75100us
+Send with: IrSender.sendNEC(0xF2, 0x87, );
+rawIRTimings[68]:
+ -744800
+ +8950,-5250
+ + 550,- 650 + 650,-1900 + 650,- 550 + 550,- 700
+ + 650,-1900 + 650,-1900 + 600,-1950 + 600,-1950
+ + 650,-1900 + 600,- 600 + 550,-2000 + 650,-1900
+ + 600,- 600 + 650,- 600 + 600,- 600 + 650,- 600
+ + 600,-1950 + 600,-1950 + 650,-1900 + 600,- 600
+ + 550,- 700 + 650,- 550 + 650,- 600 + 600,-1950
+ + 650,- 550 + 650,- 550 + 650,- 600 + 600,-1950
+ + 600,-1950 + 600,-1950 + 600,-1950 + 600,- 600
+ + 600
+Duration=75100us
+
+
+Send FAST with TinyIRSender
+Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=745000us, Duration=32150us
+Send with: IrSender.sendFAST(0x87, );
+rawIRTimings[36]:
+ -745000
+ +2050,-1250
+ + 600,-1800 + 600,-1800 + 550,-1800 + 600,- 550
+ + 500,- 650 + 550,- 600 + 550,- 600 + 600,-1800
+ + 550,- 600 + 550,- 600 + 550,- 550 + 550,-1850
+ + 600,-1800 + 600,-1750 + 600,-1800 + 550,- 600
+ 600
-Sum: 67800
+Duration=32150usDuration=67900us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first
+Protocol=Onkyo Address=0xF2, Command=0x8887, Raw-Data=0x888700F2, 32 bits, LSB first, Gap=745700us, Duration=62350us
Send with: IrSender.sendOnkyo(0xF2, 0x8887, );
-rawData[68]:
- -1053400
- +8850,-4400
- + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 550,-1650
- + 600,- 550 + 550,- 550 + 650,- 500 + 550,- 550
- + 600,- 550 + 600,- 500 + 600,- 550 + 550,- 550
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550
- + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
- + 600,- 500 + 600,- 550 + 550,- 550 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
+rawIRTimings[68]:
+ -745700
+ +8950,-4400
+ + 650,- 500 + 600,-1650 + 650,- 450 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 600,- 550 + 650,- 500
+ + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
+ + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1650
+ 600
-Sum: 62050
+Duration=62350us
+
Send Apple
-Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first
+Protocol=Apple Address=0xF2, Command=0x87, Raw-Data=0xF28787EE, 32 bits, LSB first, Gap=744200us, Duration=71250us
Send with: IrSender.sendApple(0xF2, 0x87, );
-rawData[68]:
- -1054100
+rawIRTimings[68]:
+ -744200
+ +8950,-4400
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,- 550 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 550
+ + 600,- 500 + 600,- 550 + 650,- 500 + 600,-1600
+ + 650,-1600 + 600,-1650 + 650,-1600 + 650,- 450
+ + 600,- 550 + 600,- 550 + 600,- 500 + 700,-1550
+ + 600,- 550 + 650,-1600 + 650,- 450 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650
+ + 650
+Duration=71250us
+
+
+Send Panasonic
+Protocol=Panasonic Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=744250us, Duration=60100us
+Send with: IrSender.sendPanasonic(0xF2, 0x87, );
+rawIRTimings[100]:
+ -744250
+ +3400,-1750
+ + 500,- 400 + 450,-1300 + 500,- 400 + 450,- 400
+ + 450,- 450 + 500,- 400 + 500,- 400 + 500,- 350
+ + 450,- 450 + 500,- 400 + 500,- 350 + 550,- 350
+ + 500,- 400 + 500,-1250 + 450,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,- 400 + 450,-1250 + 550,- 350 + 550,- 350
+ + 500,-1250 + 500,-1250 + 450,-1250 + 500,-1250
+ + 500,- 400 + 500,- 400 + 500,- 350 + 450,- 450
+ + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 400
+ + 450,- 400 + 550,- 350 + 500,- 400 + 450,-1250
+ + 550,- 350 + 500,- 400 + 500,- 350 + 500,-1250
+ + 450,- 450 + 500,-1250 + 500,- 400 + 450,-1300
+ + 400
+Duration=60100us
+
+
+Send Kaseikyo with extra=0x4711 as Vendor ID
+Protocol=Kaseikyo Address=0xF2, Command=0x87, Extra=0x4711, Raw-Data=0xAB870F23, 48 bits, LSB first, Gap=764450us, Duration=67100us
+Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711);
+rawIRTimings[100]:
+ -764450
+ +3500,-1700
+ + 500,-1250 + 500,- 400 + 400,- 450 + 550,- 350
+ + 500,-1250 + 500,- 400 + 450,- 450 + 450,- 400
+ + 500,-1250 + 500,-1250 + 450,-1300 + 500,- 400
+ + 500,- 400 + 450,- 400 + 500,-1250 + 500,- 350
+ + 500,-1250 + 550,-1200 + 500,- 400 + 500,- 350
+ + 500,- 400 + 500,-1250 + 500,- 400 + 400,- 500
+ + 450,-1250 + 500,-1250 + 500,-1250 + 500,-1250
+ + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 400
+ + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 350
+ + 500,- 400 + 500,- 400 + 500,- 350 + 550,-1200
+ + 500,-1250 + 500,-1250 + 500,- 400 + 450,-1250
+ + 550,- 350 + 500,-1250 + 500,- 400 + 450,-1300
+ + 500
+Duration=67100us
+
+
+Send Kaseikyo_Denon variant
+Protocol=Kaseikyo_Denon Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=764750us, Duration=63650us
+Send with: IrSender.sendKaseikyo_Denon(0xF2, 0x87, );
+rawIRTimings[100]:
+ -764750
+ +3550,-1650
+ + 500,- 400 + 500,- 400 + 500,-1200 + 550,- 350
+ + 450,-1300 + 450,- 400 + 550,-1200 + 450,- 450
+ + 500,- 400 + 400,-1300 + 550,- 350 + 500,- 400
+ + 450,-1300 + 500,-1250 + 450,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 400,- 450 + 500,- 400
+ + 450,- 450 + 400,-1300 + 500,- 450 + 450,- 400
+ + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1200
+ + 500,- 400 + 450,- 450 + 500,- 400 + 500,- 350
+ + 500,-1250 + 450,-1300 + 500,-1250 + 500,- 400
+ + 450,- 400 + 500,- 400 + 500,- 400 + 500,-1250
+ + 400,- 500 + 450,- 400 + 500,- 400 + 500,-1250
+ + 500,- 350 + 450,-1300 + 500,- 400 + 500,-1250
+ + 500
+Duration=63650us
+
+
+Send Denon with 2 autorepeats after 45 ms
+Protocol=Denon Address=0x12, Command=0x87, Raw-Data=0x10F2, 15 bits, LSB first, Gap=765050us, Duration=22400us
+Send with: IrSender.sendDenon(0x12, 0x87, );
+rawIRTimings[32]:
+ -765050
+ + 350,- 700 + 350,-1750 + 350,- 700 + 350,- 700
+ + 350,-1750 + 350,-1750 + 350,-1750 + 350,-1700
+ + 300,- 800 + 300,- 750 + 300,- 750 + 300,- 750
+ + 300,-1750 + 350,- 750 + 300,- 750 + 350
+Duration=22400us
+
+
+Send Denon/Sharp variant with 2 autorepeat5 after 45 ms
+Protocol=Sharp Address=0x12, Command=0x87, Raw-Data=0x30F2, 15 bits, LSB first, Gap=728100us, Duration=23400us
+Send with: IrSender.sendSharp(0x12, 0x87, );
+rawIRTimings[32]:
+ -728100
+ + 350,- 700 + 300,-1800 + 350,- 700 + 300,- 750
+ + 350,-1750 + 300,-1800 + 300,-1750 + 350,-1750
+ + 350,- 700 + 350,- 750 + 300,- 750 + 300,- 750
+ + 300,-1800 + 300,-1750 + 350,- 700 + 350
+Duration=23400us
+
+
+Send Sony/SIRCS with 7 command and 5 address bits
+Protocol=Sony Address=0x12, Command=0x7, Raw-Data=0x907, 12 bits, LSB first, Gap=727550us, Duration=20000us
+Send with: IrSender.sendSony(0x12, 0x7, , 12);
+rawIRTimings[26]:
+ -727550
+ +2450,- 550
+ +1300,- 500 +1250,- 600 +1250,- 550 + 650,- 550
+ + 650,- 550 + 700,- 550 + 650,- 550 + 650,- 550
+ +1250,- 600 + 700,- 500 + 700,- 500 +1250
+Duration=20000us
+
+
+Send Sony/SIRCS with 7 command and 8 address bits
+Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 15 bits, LSB first, Gap=725050us, Duration=25400us
+Send with: IrSender.sendSony(0xF2, 0x7, , 15);
+rawIRTimings[32]:
+ -725050
+ +2450,- 550
+ +1300,- 500 +1250,- 550 +1300,- 500 + 700,- 550
+ + 700,- 500 + 700,- 500 + 700,- 550 + 700,- 500
+ +1250,- 550 + 650,- 550 + 650,- 600 +1300,- 500
+ +1250,- 550 +1250,- 550 +1250
+Duration=25400us
+
+
+Send Sony/SIRCS with 7 command and 13 address bits and no repeats
+Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 20 bits, LSB first, Gap=729700us, Duration=31500us
+Send with: IrSender.sendSony(0xF2, 0x7, , 20);
+rawIRTimings[42]:
+ -729700
+ +2400,- 600
+ +1250,- 550 +1300,- 500 +1250,- 550 + 700,- 550
+ + 650,- 550 + 700,- 500 + 700,- 550 + 650,- 550
+ +1300,- 500 + 650,- 550 + 700,- 550 +1250,- 550
+ +1250,- 550 +1300,- 500 +1250,- 550 + 650,- 600
+ + 650,- 550 + 650,- 550 + 700,- 550 + 650
+Duration=31500us
+
+
+Send Samsung 8 bit command and 8 bit address
+Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x7887F2F2, 32 bits, LSB first, Gap=752900us, Duration=65650us
+Send with: IrSender.sendSamsung(0xF2, 0x87, );
+rawIRTimings[68]:
+ -752900
+ +4500,-4450
+ + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600
+ + 650,- 500 + 650,-1600 + 650,- 450 + 650,- 500
+ + 600,-1650 + 650,-1550 + 650,-1600 + 600,-1650
+ + 600,-1650 + 650,-1600 + 600,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 550 + 650,-1550
+ + 650,- 500 + 600,- 550 + 650,- 450 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600
+Duration=65650us
+
+
+Send Samsung 8 bit command and 16 bit address
+Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x788700F2, 32 bits, LSB first, Gap=747150us, Duration=60150us
+Send with: IrSender.sendSamsung(0xF2, 0x87, );
+rawIRTimings[68]:
+ -747150
+ +4500,-4400
+ + 650,- 500 + 650,-1600 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
+ + 600,- 550 + 600,- 500 + 600,- 550 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 700,- 450
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 500 + 650,-1600
+ + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1600
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ + 650
+Duration=60150us
+
+
+Send Samsung 16 bit command and address
+Protocol=Samsung Address=0xF2, Command=0xA987, Raw-Data=0xA98700F2, 32 bits, LSB first, Gap=746700us, Duration=60200us
+Send with: IrSender.sendSamsung(0xF2, 0xA987, );
+rawIRTimings[68]:
+ -746700
+ +4450,-4450
+ + 650,- 500 + 600,-1650 + 600,- 500 + 600,- 550
+ + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650
+ + 600,- 550 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,- 550 + 600,- 500 + 700,- 450 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500
+ + 600,- 550 + 600,- 550 + 600,- 500 + 600,-1650
+ + 650,-1600 + 650,- 500 + 650,- 500 + 600,-1600
+ + 600,- 550 + 600,-1650 + 600,- 500 + 650,-1600
+ + 650
+Duration=60200us
+
+
+Send Samsung48 16 bit command
+Protocol=Samsung48 Address=0xF2, Command=0xA987, Raw-Data=0x56A9, 48 bits, LSB first, Gap=746150us, Duration=87100us
+Send with: IrSender.sendSamsung48(0xF2, 0xA987, );
+rawIRTimings[100]:
+ -746150
+ +4550,-4350
+ + 650,- 500 + 650,-1600 + 600,- 550 + 600,- 500
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550
+ + 650,-1550 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600
+ + 600,- 550 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,-1600 + 600,-1650 + 650,- 500
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,-1650 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550
+ + 600,-1650 + 600,- 500 + 650,-1600 + 650,- 500
+ + 600
+Duration=87100us
+
+
+Send RC5
+Protocol=RC5 Address=0x12, Command=0x7, Toggle=1, Raw-Data=0x1C87, 13 bits, MSB first, Gap=762250us, Duration=24200us
+Send with: IrSender.sendRC5(0x12, 0x7, );
+rawIRTimings[24]:
+ -762250
+ + 950,- 850
+ + 950,- 800 +1000,- 850 +1850,- 800 + 950,-1750
+ +1800,- 850 + 950,- 850 + 950,- 800 +1000,-1700
+ + 900,- 850 +1000,- 800 +1000
+Duration=24200us
+
+
+Send RC5X with 7.th MSB of command set
+Protocol=RC5 Address=0x12, Command=0x47, Raw-Data=0x487, 13 bits, MSB first, Gap=724200us, Duration=24150us
+Send with: IrSender.sendRC5(0x12, 0x47, );
+rawIRTimings[22]:
+ -724200
+ +1850,- 800
+ + 950,-1750 +1800,- 850 + 950,-1750 +1850,- 800
+ + 950,- 800 +1000,- 800 + 950,-1750 + 950,- 800
+ +1000,- 800 +1000
+Duration=24150us
+
+
+Send Marantz with RC5 and extra=0x38
+Protocol=Marantz Address=0x12, Command=0x7, Extra=0x38, Toggle=1, Raw-Data=0x721F8, 19 bits, MSB first, Gap=722250us, Duration=37500us
+Send with: IrSender.sendMarantz(0x12, 0x7, , 0x38);
+rawIRTimings[34]:
+ -722250
+ + 950,- 850
+ + 950,- 850 + 900,- 850 +1900,- 800 + 900,-1800
+ +1800,-4350 +1000,- 800 + 950,- 850 + 950,-1750
+ + 900,- 850 +1000,- 750 +1000,- 850 + 950,- 850
+ + 900,- 850 +1850,- 800 +1000,- 850 + 900
+Duration=37500us
+
+
+Send Marantz with RC5A and extra=0x38
+Protocol=Marantz Address=0x12, Command=0x47, Extra=0x38, Raw-Data=0x121F8, 19 bits, MSB first, Gap=732750us, Duration=37550us
+Send with: IrSender.sendMarantz(0x12, 0x47, , 0x38);
+rawIRTimings[32]:
+ -732750
+ +1850,- 800
+ + 950,-1700 +1850,- 850 + 900,-1800 +1800,-4400
+ +1000,- 800 + 950,- 800 +1000,-1700 + 950,- 850
+ + 950,- 850 + 900,- 900 + 950,- 800 + 950,- 850
+ +1850,- 850 + 900,- 850 +1000
+Duration=37550us
+
+
+Send RC6
+Protocol=RC6 Address=0xF2, Command=0x87, Toggle=1, Raw-Data=0x1F287, 20 bits, MSB first, Gap=727650us, Duration=23200us
+Send with: IrSender.sendRC6(0xF2, 0x87, );
+rawIRTimings[36]:
+ -727650
+ +2750,- 750
+ + 550,- 800 + 600,- 350 + 550,- 400 +1400,- 850
+ + 500,- 400 + 550,- 350 + 550,- 350 + 550,- 850
+ + 550,- 350 +1000,- 850 + 950,- 850 + 550,- 350
+ + 500,- 400 + 550,- 350 +1000,- 400 + 550,- 350
+ + 550
+Duration=23200us
+
+
+Send RC6A with 14 bit and extra=0x2711
+Protocol=RC6A Address=0xF2, Command=0x87, Extra=0x2711, Raw-Data=0x2711F287, 35 bits, MSB first, Gap=730650us, Duration=37000us
+Send with: IrSender.sendRC6A(0xF2, 0x87, , 0x2711);
+rawIRTimings[60]:
+ -730650
+ +2750,- 800
+ + 500,- 400 + 500,- 400 + 550,- 850 + 500,- 850
+ + 950,- 400 +1000,- 850 + 500,- 400 +1000,- 400
+ + 500,- 450 + 450,- 850 + 500,- 450 + 500,- 400
+ + 950,- 900 + 500,- 400 + 500,- 400 +1050,- 350
+ + 500,- 400 + 500,- 400 + 500,- 450 + 500,- 800
+ + 600,- 350 +1000,- 850 +1000,- 800 + 550,- 400
+ + 500,- 450 + 500,- 400 +1000,- 400 + 550,- 350
+ + 500
+Duration=37000us
+
+
+Send MagiQuest, WandId=0x6BCD00F2
+Protocol=MagiQuest Address=0xF2, Command=0x187, Raw-Data=0x6BCD00F2, 56 bits, MSB first, Gap=744850us, Duration=64800us
+Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, );
+rawIRTimings[112]:
+ -744850
+ + 400,- 750 + 400,- 800 + 350,- 800 + 400,- 800
+ + 350,- 800 + 400,- 800 + 350,- 800 + 350,- 850
+ + 650,- 550 + 600,- 550 + 350,- 800 + 600,- 600
+ + 350,- 800 + 600,- 550 + 650,- 550 + 650,- 500
+ + 650,- 500 + 400,- 800 + 350,- 800 + 650,- 550
+ + 600,- 550 + 350,- 800 + 650,- 550 + 350,- 800
+ + 400,- 800 + 350,- 800 + 400,- 800 + 350,- 800
+ + 350,- 800 + 400,- 800 + 400,- 750 + 650,- 550
+ + 600,- 550 + 650,- 500 + 700,- 500 + 350,- 800
+ + 400,- 750 + 650,- 550 + 350,- 850 + 600,- 550
+ + 650,- 550 + 350,- 800 + 350,- 800 + 350,- 850
+ + 350,- 800 + 650,- 500 + 650,- 550 + 650,- 550
+ + 400,- 750 + 400,- 800 + 600,- 550 + 350,- 800
+ + 400,- 800 + 350,- 800 + 650,- 500 + 400
+Duration=64800us
+
+
+Send OpenLASIR mode fire and color orange, detected as ONKYO
+Protocol=Onkyo Address=0xF2, Command=0xC087, Raw-Data=0xC0870DF2, 32 bits, LSB first, Gap=793250us, Duration=65650us
+Send with: IrSender.sendOnkyo(0xF2, 0xC087, );
+rawIRTimings[68]:
+ -793250
+8900,-4450
- + 550,- 550 + 600,-1650 + 600,-1650 + 600,-1650
- + 550,- 550 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550
- + 600,- 500 + 600,- 600 + 550,- 500 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
- + 550,- 550 + 600,-1650 + 550,- 550 + 600,- 550
- + 550,-1650 + 600,-1650 + 600,-1650 + 550,-1650
+ + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
+ + 650,-1600 + 650,- 450 + 600,-1650 + 650,-1600
+ + 650,- 500 + 600,- 500 + 600,- 550 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 650,- 450
+ + 650,- 500 + 700,- 450 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500
+ + 600,- 500 + 600,- 550 + 600,-1650 + 600,-1650
+ + 600
+Duration=65650us
+
+
+Send Lego with 2 channel and with 4 command bits
+Protocol=Lego Address=0x2, Command=0x17, Raw-Data=0x217B, 16 bits, MSB first, Gap=747400us, Duration=10850us
+Send with: IrSender.sendLego(0x2, 0x17, );
+rawIRTimings[36]:
+ -747400
+ + 250,- 950
+ + 200,- 550 + 250,- 500 + 200,- 150 + 300,- 500
+ + 200,- 500 + 250,- 500 + 250,- 500 + 250,- 200
+ + 200,- 500 + 250,- 150 + 300,- 150 + 250,- 250
+ + 200,- 250 + 250,- 450 + 250,- 200 + 250,- 150
+ + 300
+Duration=10850us
+
+
+Send 16 bit Bang&Olufsen - requires originally 455 kHz
+- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
+rawIRTimings[86]:
+ -749450
+ + 250,-2850
+ + 300,-2800 + 300,-12750 + 300,-2850 + 250,-9050
+ + 300,-5900 + 300,-5900 + 250,-5950 + 300,-2850
+ + 250,-5950 + 250,-9050 + 250,-2850 + 300,-9000
+ + 300,-2800 + 250,-6000 + 250,-5950 + 300,-5900
+ + 300,-9000 + 300,-5950 + 250,-5950 + 300,-12100
+ + 300,-2850 + 300,-2800 + 250,-12750 + 250,-2850
+ + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950
+ + 250,-2850 + 300,-5900 + 300,-9000 + 300,-2850
+ + 250,-9050 + 250,-2850 + 300,-5950 + 250,-5950
+ + 250,-5950 + 300,-9000 + 300,-5900 + 250,-6000
+ + 250,-12150 + 250
+Duration=274750us
+
+- Now try to decode the first 6 entries, which results in rawData 0x0
+Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=749450us, Duration=6500us
+
+- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
+Protocol=Bang&Olufsen Address=0xF2, Command=0x87, Raw-Data=0xF287, 16 bits, MSB first, Gap=12750us, Duration=255500us
+Send with: IrSender.sendBang&Olufsen(0xF2, 0x87, );
+rawIRTimings[80]:
+ -12750
+ + 300,-2850
+ + 250,-9050 + 300,-5900 + 300,-5900 + 250,-5950
+ + 300,-2850 + 250,-5950 + 250,-9050 + 250,-2850
+ + 300,-9000 + 300,-2800 + 250,-6000 + 250,-5950
+ + 300,-5900 + 300,-9000 + 300,-5950 + 250,-5950
+ + 300,-12100 + 300,-2850 + 300,-2800 + 250,-12750
+ + 250,-2850 + 300,-9000 + 300,-5900 + 300,-5950
+ + 250,-5950 + 250,-2850 + 300,-5900 + 300,-9000
+ + 300,-2850 + 250,-9050 + 250,-2850 + 300,-5950
+ + 250,-5950 + 250,-5950 + 300,-9000 + 300,-5900
+ + 250,-6000 + 250,-12150 + 250
+Duration=255500us
+
+
+Send next protocols with IrSender.write
+
+Send JVC
+Protocol=JVC Address=0xF2, Command=0x87, Raw-Data=0x87F2, 16 bits, LSB first, Gap=850000us, Duration=39600us
+Send with: IrSender.sendJVC(0xF2, 0x87, );
+rawIRTimings[36]:
+ -850000
+ +8400,-4150
+ + 650,- 400 + 600,-1500 + 650,- 450 + 600,- 500
+ + 550,-1500 + 550,-1600 + 600,-1500 + 550,-1550
+ + 600,-1500 + 600,-1500 + 600,-1550 + 550,- 500
+ + 600,- 450 + 550,- 550 + 550,- 500 + 600,-1500
+ + 600
+Duration=39600us
+
+
+Send LG
+Protocol=LG Address=0xF2, Command=0xA987, Raw-Data=0xF2A9872, 28 bits, MSB first, Gap=726100us, Duration=57800us
+Send with: IrSender.sendLG(0xF2, 0xA987, );
+rawIRTimings[60]:
+ -726100
+ +8950,-4150
+ + 550,-1550 + 550,-1500 + 600,-1500 + 600,-1500
+ + 550,- 500 + 650,- 450 + 550,-1500 + 550,- 500
+ + 600,-1500 + 550,- 500 + 550,-1550 + 600,- 450
+ + 600,-1500 + 600,- 450 + 600,- 450 + 600,-1500
+ + 600,-1500 + 550,- 500 + 600,- 450 + 600,- 500
+ + 550,- 500 + 600,-1500 + 550,-1500 + 600,-1500
+ + 600,- 450 + 550,- 550 + 550,-1500 + 600,- 500
+ + 600
+Duration=57800us
+
+
+Send Bosewave with no address and 8 command bits
+Protocol=BoseWave Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=762350us, Duration=27150us
+Send with: IrSender.sendBoseWave(0x0, 0x87, );
+rawIRTimings[36]:
+ -762350
+ +1100,-1400
+ + 600,-1400 + 600,-1400 + 600,-1400 + 600,- 400
+ + 600,- 450 + 600,- 400 + 550,- 450 + 550,-1450
+ + 550,- 450 + 600,- 400 + 600,- 400 + 550,-1450
+ + 600,-1400 + 600,-1400 + 550,-1450 + 600,- 450
+ + 550
+Duration=27150us
+
+
+Send FAST
+Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=726950us, Duration=29200us
+Send with: IrSender.sendFAST(0x87, );
+rawIRTimings[36]:
+ -726950
+ +2200,-1000
+ + 600,-1500 + 600,-1500 + 550,-1550 + 600,- 500
+ + 600,- 500 + 550,- 500 + 550,- 500 + 600,-1500
+ + 600,- 450 + 600,- 500 + 550,- 500 + 600,-1500
+ + 600,-1550 + 600,-1500 + 550,-1550 + 600,- 500
+ + 550
+Duration=29200us
+
+
+Force buffer overflow by sending 450 marks and spaces
+rawIRTimings[400]:
+ -725800
+ + 300,- 450
+ + 300,- 500 + 200,- 550 + 300,- 450 + 250,- 550
+ + 300,- 450 + 300,- 450 + 300,- 500 + 250,- 500
+ + 200,- 550 + 300,- 500 + 200,- 550 + 300,- 500
+ + 250,- 500 + 200,- 600 + 250,- 500 + 250,- 500
+ + 200,- 550 + 250,- 550 + 250,- 500 + 250,- 500
+ + 200,- 550 + 300,- 500 + 200,- 550 + 250,- 500
+ + 300,- 500 + 200,- 550 + 200,- 550 + 300,- 450
+ + 300,- 500 + 200,- 550 + 200,- 550 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500
+ + 300,- 450 + 300,- 500 + 300,- 450 + 250,- 500
+ + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500
+ + 300,- 450 + 300,- 500 + 250,- 500 + 300,- 450
+ + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500
+ + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500
+ + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500
+ + 200,- 550 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 200,- 550
+ + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 500 + 300,- 500
+ + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 500 + 250,- 550 + 250,- 500 + 250,- 550
+ + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 500
+ + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 500 + 250,- 500 + 300,- 500
+ + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500
+ + 300,- 450 + 200,- 600 + 250,- 500 + 300,- 450
+ + 250,- 500 + 250,- 550 + 300,- 450 + 250,- 500
+ + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550
+ + 250,- 500 + 300,- 450 + 250,- 550 + 300,- 450
+ + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 300,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 300,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 500 + 200,- 550
+ + 300,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 500 + 250,- 550 + 200,- 550
+ + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500
+ + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 500 + 250,- 550 + 200,- 600 + 200,- 500
+ + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500
+ + 250,- 600 + 200,- 550 + 200
+Duration=152850us
+
+Invert toggle value for next loop
+Stop receiver
+Start receiver
+
+address=0x1F3 command=0x98 repeats=2
+
+Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2
+Protocol=NEC Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Gap=915450us, Duration=67850us
+Send with: IrSender.sendNEC(0xF3, 0x98, );
+rawIRTimings[68]:
+ -915450
+ +8900,-4450
+ + 600,-1600 + 650,-1600 + 600,- 550 + 600,- 500
+ + 700,-1550 + 600,-1650 + 650,-1600 + 600,-1600
+ + 600,- 550 + 600,- 550 + 650,-1600 + 600,-1600
+ + 650,- 500 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,- 500 + 650,- 450 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,- 450 + 650,-1600 + 650,-1600 + 600,- 550
+ 600
-Sum: 71000
+Duration=67850us
+
+Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69250us, Duration=67900us
+Send with: IrSender.sendNEC2(0xF3, 0x98, );
+rawIRTimings[68]:
+ -69250
+ +8900,-4400
+ + 650,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 650,-1600 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500
+ + 600,- 550 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650
+Duration=67900us
+
+
+Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69850us, Duration=67900us
+Send with: IrSender.sendNEC2(0xF3, 0x98, );
+rawIRTimings[68]:
+ -69850
+ +8950,-4400
+ + 650,-1600 + 600,-1650 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,- 550 + 600,- 500 + 650,-1600 + 650,-1600
+ + 650,- 450 + 650,- 500 + 650,- 500 + 650,- 450
+ + 600,- 550 + 650,- 450 + 650,- 500 + 650,-1600
+ + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1650
+ + 650,-1550 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450
+ + 650
+Duration=67900us
diff --git a/examples/UnitTest/UnitTest_64bit.log b/examples/UnitTest/UnitTest_64bit.log
index e69f1c73b..82e257d33 100644
--- a/examples/UnitTest/UnitTest_64bit.log
+++ b/examples/UnitTest/UnitTest_64bit.log
@@ -1,640 +1,740 @@
-START UnitTest.cpp from Feb 24 2023
-Using library version 4.1.0
-Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 14
-Send IR signals at pin 12
-If you connect debug pin 13 to ground, raw data is always printed
-Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 600 ns, total period is 26 us
+START C:\Users\armin\AppData\Local\Temp\.arduinoIDE-unsaved2025614-8520-1rntouk.pt81h\UnitTest\UnitTest.ino from Jul 14 2025
+Using library version 4.4.2
+Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave, MagiQuest, Universal Pulse Distance Width, Hash at pin 15
+Use ReceiveCompleteCallback
+Receive buffer length is 750
+Send IR signals at pin 4
+If you connect debug pin 16 to ground, raw data is always printed
16000 us is the (minimum) gap, after which the start of a new IR packet is assumed
-100 us are subtracted from all marks and added to all spaces for decoding
+20 us are subtracted from all marks and added to all spaces for decoding
address=0xFFF1 command=0x76
Send NEC with 8 bit address
-Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
+Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Gap=1047000us Duration=68250us
Send with: IrSender.sendNEC(0xF1, 0x76, );
-rawData[68]:
- -1050650
+rawData[68]:
+ -1047000
+9050,-4450
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,-1600
- + 700,- 450 + 650,-1600 + 650,-1650 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,- 450 + 650,-1600 + 650,-1600 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,- 450 + 700,- 450 + 650,-1600
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,-1600
- + 700
-Sum: 68500
+ + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650,- 500 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,-1650 + 650,- 500 + 600,- 500 + 650,-1650
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1650
+ + 600
+Duration=68250us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1067700us Duration=73800us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1060200
- +9050,-4400
- + 650,-1600 + 650,- 500 + 650,- 450 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1650 + 650,- 450
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600
- + 650
-Sum: 74050
+rawData[68]:
+ -1067700
+ +9050,-4450
+ + 550,-1650 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,-1650
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,-1650
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,-1650 + 550,- 550 + 600,- 550 + 600,-1650
+ + 600,- 500 + 600,- 550 + 600,- 500 + 650,-1650
+ + 600
+Duration=73800us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1067300us Duration=73750us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1060450
- +9050,-4450
- + 650,-1600 + 650,- 500 + 650,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 500
- + 650,-1600 + 650,- 500 + 650,- 500 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650
-Sum: 74150
+rawData[68]:
+ -1067300
+ +9000,-4450
+ + 600,-1650 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 650,-1600 + 600,-1650 + 600,-1650
+ + 600,- 550 + 650,-1600 + 600,-1650 + 600,- 500
+ + 650,-1650 + 550,-1650 + 650,-1650 + 550,- 550
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 550 + 650,- 450 + 650,-1650
+ + 550
+Duration=73750us
+
Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats
-Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
+Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first Gap=1071500us Duration=68500us
Send with: IrSender.sendNEC(0x80, 0x45,