初始化提交

This commit is contained in:
王立帮
2024-07-20 22:09:06 +08:00
commit c247dd07a6
6876 changed files with 2743096 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
nbproject
api-doc
*~
docs

View File

@@ -0,0 +1,13 @@
# Contribution Guidelines
This library is the culmination of the expertise of many members of the open source community who have dedicated their time and hard work.
The best way to ask for help or propose a new idea is to create a new discussion and / or a new Pull Request
with your code changes to allow you to share your own innovations with the rest of the community.
The following are some guidelines to observe when creating discussions / PRs:
- Be friendly; it is important that we can all enjoy a safe space as we are all working on the same project and **it is okay for people to have different ideas**.
- Use reasonable titles; refrain from using overly long or capitalized titles as they are usually annoying and do little to encourage others to help :smile:.
- Use the style; we use the original [C Style by Kerninghan / Ritchie](https://en.wikipedia.org/wiki/Indentation_style#K&R_style) in [variant: 1TBS (OTBS)](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)).
In short: 4 spaces indentation, no tabs, opening braces on the same line, braces are mandatory on all if/while/do, no hard line length limit.
To beautify your code, you may use the online formatter [here](https://www.freecodeformat.com/c-format.php).
- Cover **all** occurences of the problem / addition you address with your PR. Do not forget the documentation like it is done for existing code. Code changes without proper documentation will be rejected!

View File

@@ -0,0 +1,30 @@
## Contributors
These are the active contributors of this project that you may contact if there is anything you need help with or if you have suggestions.
- [ArminJo](https://github.com/ArminJo) Maintainer
- [z3t0](https://github.com/z3t0) the main contributor until version 2.4.0.
* Email: zetoslab@gmail.com
- [shirriff](https://github.com/shirriff): An amazing person who worked to create this awesome library and provide unending support
- [Informatic](https://github.com/Informatic)
- [fmeschia](https://github.com/fmeschia)
- [PaulStoffregen](https://github.com/paulstroffregen)
- [crash7](https://github.com/crash7)
- [Neco777](https://github.com/neco777)
- [Lauszus](https://github.com/lauszus)
- [csBlueChip](https://github.com/csbluechip) contributed major and vital changes to the code base.
- [Sebazzz](https://github.com/sebazz)
- [lumbric](https://github.com/lumbric)
- [ElectricRCAircraftGuy](https://github.com/electricrcaircraftguy)
- [philipphenkel](https://github.com/philipphenkel)
- [MCUdude](https://github.com/MCUdude)
- [adamlhumphreys](https://github.com/adamlhumphreys) (code space improvements)
- [marcmerlin](https://github.com/marcmerlin) (ESP32 port)
- [MrBryonMiller](https://github.com/MrBryonMiller)
- [bengtmartensson](https://github.com/bengtmartensson) providing support
- [AnalysIR](https:/github.com/AnalysIR) providing support
- [eshicks4](https://github.com/eshicks4)
- [Jim-2249](https://github.com/Jim-2249)
- [pmalasp](https://github.com/pmalasp )
Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
MIT License
(c) Copyright 2009 Ken Shirriff http://www.righto.com
(c) Copyright 2016 Rafi Khan
(c) Copyright 2020 Armin Joachimsmeyer et al.
http://www.opensource.org/licenses/mit-license.php
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.

View File

@@ -0,0 +1,631 @@
# IRremote Arduino Library
This library enables you to send and receive using infra-red signals on an Arduino.
### [Version 3.7.1](https://github.com/Arduino-IRremote/Arduino-IRremote/archive/master.zip) - work in progress
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)
[![Installation instructions](https://www.ardu-badge.com/badge/IRremote.svg?)](https://www.ardu-badge.com/IRremote)
[![LibraryBuild](https://github.com/Arduino-IRremote/Arduino-IRremote/workflows/LibraryBuild/badge.svg)](https://github.com/Arduino-IRremote/Arduino-IRremote/actions)
Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libraries/i-rremote).
# Table of content
- [API](https://github.com/Arduino-IRremote/Arduino-IRremote#api)
- [Installation](https://github.com/Arduino-IRremote/Arduino-IRremote#installation)
- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-ir-protocols)
- [Old Wiki](https://github.com/Arduino-IRremote/Arduino-IRremote#old-wiki)
- [Features of the 3.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#features-of-the-3x-version)
* [Converting your 2.x program to the 3.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-3x-version)
+ [Example](https://github.com/Arduino-IRremote/Arduino-IRremote#example)
* [Do not want to convert your 2.x program and use the 3.x library version?](https://github.com/Arduino-IRremote/Arduino-IRremote#do-not-want-to-convert-your-2x-program-and-use-the-3x-library-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 old tutorials and the 3.x versions](https://github.com/Arduino-IRremote/Arduino-IRremote#errors-with-old-tutorials-and-the-3x-versions)
- [Why *.hpp files instead of *.cpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-files-instead-of-cpp-files)
- [Using the new *.hpp files / how to avoid `multiple definitions` linker errors](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files--how-to-avoid-multiple-definitions-linker-errors)
- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes)
* [Minimal NEC receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver)
- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes)
+ [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases)
- [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 frequency](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-cpu-frequency)
- [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)
- [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-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)
* [Increase sending power](https://github.com/Arduino-IRremote/Arduino-IRremote#increase-sending-power)
- [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)
- [Revision History](https://github.com/Arduino-IRremote/Arduino-IRremote#revision-history)
- [Contributing](https://github.com/Arduino-IRremote/Arduino-IRremote#contributing)
* [Adding new protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#adding-new-protocols)
+ [Integration](https://github.com/Arduino-IRremote/Arduino-IRremote#integration)
+ [Creating API documentation](https://github.com/Arduino-IRremote/Arduino-IRremote#creating-api-documentation)
* [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote#contributors)
- [License](https://github.com/Arduino-IRremote/Arduino-IRremote#license)
* [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote#copyright)
# API
A Doxygen documentation of the sources is available on the [project homepage](https://arduino-irremote.github.io/Arduino-IRremote/classIRrecv.html).
# Installation
Click on the LibraryManager badge above to see the [instructions](https://www.ardu-badge.com/IRremote/zip).
# Supported IR Protocols
Denon / Sharp, JVC, LG, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BoseWave, Lego, Whynter and optional MagiQuest.<br/>
Protocols can be switched off and on by defining macros before the line `#include <IRremote.hpp>` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L14):
```c++
#define DECODE_NEC
//#define DECODE_DENON
#include <IRremote.hpp>
```
# [Old Wiki](https://github.com/Arduino-IRremote/Arduino-IRremote/wiki)
This is a quite old but maybe useful [wiki](https://github.com/Arduino-IRremote/Arduino-IRremote/wiki) for this library.
# Features of the 3.x version
- You can use any pin for sending now, like you are used with receiving.
- Simultaneous sending and receiving. See the [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino#L167-L170) example.
- No more need to use 32 bit hex values in your code. Instead a (8 bit) command value is provided for decoding (as well as an 16 bit address and a protocol number).
- Protocol values comply to protocol standards, i.e. NEC, Panasonic, Sony, Samsung and JVC decode and send LSB first.
- Supports more protocols, since adding a protocol is quite easy now.
- Better documentation and more examples :-).
- Compatible with tone() library, see [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169).
- Supports more platforms, since the new structure allows to easily add a new platform.
- Feedback LED also for sending.
- Ability to generate a non PWM signal to just simulate an active low receiver signal for direct connect to existent receiving devices without using IR.
- Easy configuration of protocols required, directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57). This reduces the memory footprint and increases decoding time.
## Converting your 2.x program to the 3.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**.<br/>
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.
- Now there is an **IRreceiver** and **IRsender** object 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().<br/>
For sending, call `IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK);` or `IrSender.begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK);` in setup().
- 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/IRremoteInt.h#L164-L187).
- Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`.
### Example
#### 2.x program:
```c++
#include <IRremote.h>
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
}
...
}
```
#### 3.x program:
```c++
#include <IRremote.hpp>
void setup()
{
...
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
}
void loop() {
if (IrReceiver.decode()) {
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
IrReceiver.printIRResultShort(&Serial); // optional use new print version
...
IrReceiver.resume(); // Enable receiving of the next value
}
...
}
```
## Do not want to convert your 2.x program and use the 3.x library version?
First consider to just use 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.<br/>
If not, the 3.x versions try to be backwards compatible, so you can easily run your old examples. But some functions like e.g. `sendNEC()` -see below- could not made backwards compatible.
The (old and deprecated) call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`!<br/>
But only the following decoders are available then: Denon, JVC, LG, NEC, Panasonic, RC5, RC6, Samsung, Sony.
The old functions `sendNEC()` and `sendJVC()` are deprecated and renamed to `sendNECMSB()` and `sendJVCMSB()`,
to make it clearer that they send data with MSB first, which is not the standard for NEC and JVC.
Use them to send your **old MSB-first 32 bit IR data codes**.
In the new version you will send NEC (and other) commands not by 32 bit codes but by a (constant) 8 bit address and an 8 bit command.
## 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!<br/>
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.<br/><br/>
Example:
- 0xCB340102 byte reverse -> 02 01 34 CB. Bit reverse of byte -> 40 80 2C D3.
- 0xCB340102 nibble reverse -> 201043BC. Bit reverse of nibble -> 40802CD3.<br/>
Nibble reverse map: | 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 11001011001101000000000100000010.<br/>
0x40802CD3 is binary 01000000100000000010110011010011.<br/>
If you read the first binary sequence backwards (right to left), you get the second sequence.
# Errors with old tutorials and the 3.x versions
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...
# Why *.hpp files 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*.<br/>
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?**<br/>
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.
They add these options at each compiler call e.g. `-DTRACE`.<br/>
But Arduino lacks this feature. So the **workaround** is not to compile all sources separately, but to concatenate them to one huge source file by including them in your source.
This is done by e.g. `#include "ServoEasing.hpp"`.<br/>
But why not `#include "ServoEasing.cpp"`?<br/>
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.
# Using the new *.hpp files / how to avoid `multiple definitions` linker errors
In order to support [compile options](#compile-options--macros-for-this-library) more easily,
the line `#include <IRremote.h>` must be changed to `#include <IRremote.hpp>`,
but only in your **main program (aka *.ino file with setup() and loop())**, like it is done in the examples.<br/>
In **all other files** you must use
```c++
#define USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE
#include <IRremote.hpp>
```
otherwise you will get tons of **"multiple definition"** errors.<br/>
Take care that all macros you define in your main program before `#include <IRremote.hpp>`,
especially: `RAW_BUFFER_LENGTH`, `IR_SEND_PIN` and `SEND_PWM_BY_TIMER` should also be specified before this special include,
otherwise they are set to default values in *IRremote.hpp*!
# Receiving IR codes
Check for **available data** can be done by `if (IrReceiver.decode()) {`. This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`.
```c++
struct IRData {
decode_type_t protocol; // UNKNOWN, NEC, SONY, RC5, ...
uint16_t address; // Decoded address
uint16_t command; // Decoded command
uint16_t extra; // Used by MagiQuest and for Kaseikyo unknown vendor ID. Ticks used for decoding Distance protocol.
uint16_t numberOfBits; // Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; // See IRDATA_FLAGS_* definitions above
uint32_t decodedRawData; // Up to 32 bit decoded raw data, used for sendRaw functions.
irparams_struct *rawDataPtr; // Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
};
```
To access e.g. the **RAW data**, use `uint32_t myRawdata= IrReceiver.decodedIRData.decodedRawData;`.<br/>
The content of the `IrReceiver.decodedIRData.flags` is described [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L164-L175).<br/>
To **print all fields**, use `IrReceiver.printIRResultShort(&Serial);`.<br/>
To print the **raw timing data** received, use `IrReceiver.printIRResultRawFormatted(&Serial, true);`.
## Minimal NEC receiver
For applications only requiring NEC protocol, there is a receiver which has very **small code size of 500 bytes and does NOT require any timer**. See the MinimalReceiver and IRDispatcherDemo example how to use it.
# Sending IR codes
Please do not use the old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)`,
even if this functions are used in a lot of **(old)** tutorials. They are only kept for backward compatibility and unsupported and error prone.<br/>
**Much better** is to use the **new structured functions** with address and command parameters like e.g. `IrSender.sendNEC(0xA8, 0x19, 2)`.
Especially if you are able to receive these remote codes and get the address and command values.
You will discover that **the address is a constant** and the commands sometimes are sensibly grouped.
### List of public IR code databases
http://www.harctoolbox.org/IR-resources.html
# FAQ and hints
## Problems with Neopixels, FastLed etc.
IR will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 µs).<br/>
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.<br/>
You can try 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.<br/>
There are some other solutions to this on more powerful processors,
[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 if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.
This is often due to resource conflicts with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage).
## Multiple IR receiver
You can use **multiple IR receiver** by just 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.
## Increase strength of sent output signal
To **increase strength of sent output signal** you can increase the current through the send diode, and/or use 2 diodes in series,
since one IR diode requires only 1.5 volt.
## Minimal CPU frequency
For receiving, the **minimal CPU frequency is 4 MHz**, since the 50 µs timer ISR takes around 12 µs on a 16 MHz ATmega.<br/>
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`.
# Handling unknown Protocols
## Disclaimer
**This library was never designed to handle long codes like the ones used by air conditioners.**<br/>
For air conditioners [see this fork](https://github.com/crankyoldgit/IRremoteESP8266) which supports an impressive set of protocols and a lot of air conditioners and 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).<br/>
The main reason is, that it 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.
## 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 calling sendPulseDistanceWidthData() twice, once for the first 32 bit and next for the remaining 24 bits.<br/>
**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, it is likely, that your receiver circuit 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 <IRremote.hpp>` 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/ukw100/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).
# Examples for this library
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.
### SimpleReceiver + SimpleSender
This examples are a good starting point.
### ReceiveDemo
Receives all protocols and **generates a beep with the Arduino tone() function** on each packet received. By connecting pin 5 to ground, you can see the raw values for each packet. **Example how to use IRremote and tone() together**.
### ReceiveDump
Receives all protocols and dumps the received signal in different flavors. Since the printing takes so much time, repeat signals may be skipped or interpreted as UNKNOWN.
### SendDemo
Sends all available protocols at least once.
### SendAndReceive + UnitTest
ReceiveDemo + SendDemo in one program. **Receiving while sending**.
### ReceiveAndSend
Record and **play back last received IR signal** at button press.
### ReceiveOneAndSendMultiple
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.
### SmallReceiver
If **code size** matters, look at these example.<br/>
### MinimalReceiver
The MinimalReceiver example uses the **TinyReceiver** library which can **only receive NEC codes, but does not require any timer**.<br/>
MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299034264157028877).
Click on the receiver while simulation is running to specify individual IR codes.
### IRDispatcherDemo
Framework for **calling different functions of your program** for different IR codes.
### IRrelay
**Control a relay** (connected to an output pin) with your remote.
### IRremoteExtensionTest
Example for a user defined class, which itself uses the IRrecv class from IRremote.
### SendLGAirConditionerDemo
Example for sending LG air conditioner IR codes controlled by Serial input.<br/>
By just using the function `bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter)` you can control the air conditioner by any other command source.<br/>
The file *acLG.h* contains the command documentation of the LG air conditioner IR protocol. Based on reverse engineering of the LG AKB73315611 remote.
![LG AKB73315611 remote](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/LG_AKB73315611.jpg)
### ReceiverTimingAnalysis
This example analyzes the signal delivered by your IR receiver module.
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.<br/>
It also computes the `MARK_EXCESS_MICROS` value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.<br/>
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656).
Click on the receiver while simulation is running to specify individual NEC IR codes.
# 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!**
# Compile options / macros for this library
To customize the library to different requirements, there are some compile options / macros available.<br/>
These macros must be defined in your program before the line `#include <IRremote.hpp>` 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. |
| `IR_SEND_PIN` | disabled | If specified (as constant), reduces program size and improves send timing for AVR. If you want to use a runtime variable send pin e.g. with `setSendPin(uint8_t aSendPinNumber)` , you must disable this macro. |
| `SEND_PWM_BY_TIMER` | disabled | Disable carrier PWM generation in software and use (restricted) hardware PWM. Enabled for ESP32 and RP2040 in all examples. |
| `USE_NO_SEND_PWM` | disabled | Use no carrier PWM, just simulate an **active low** receiver signal. Overrides `SEND_PWM_BY_TIMER` definition. |
| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | 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! |
| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | If activated, BOSEWAVE, WHYNTER and LEGO_PF are excluded in `decode()` and in sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | If activated, the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) are excluded in `decode()`. Saves up to 1000 bytes program memory. |
| `DECODE_<Protocol name>` | 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) |
| `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.<br/>Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.<br/>Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.<br/>Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
| `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 | This completely disables the LED feedback code for send and receive, thus saving around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR processing time. |
| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. |
| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
| `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. |
| `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 <TinyIRReceiver.hpp>` to take effect.
| Name | Default value | Description |
|-|-|-|
| `IR_INPUT_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. |
| `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. |
| `NO_LED_FEEDBACK_CODE` | disabled | Enable it to disable the feedback LED function. Saves 14 bytes program memory. |
### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.<br/>
If you have not yet saved the example as your own sketch, then you are instantly in the right library folder.<br/>
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.<br/>
In both cases the library source and include files are located in the libraries `src` directory.<br/>
The modification must be renewed for each new library version!
### Modifying compile options / macros with PlatformIO
If you are using PlatformIO, you can define the macros in the *[platformio.ini](https://docs.platformio.org/en/latest/projectconf/section_env_build.html)* file with `build_flags = -D MACRO_NAME` or `build_flags = -D MACRO_NAME=macroValue`.
### Modifying compile options / macros with Sloeber IDE
If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easily define global symbols with *Properties > Arduino > CompileOptions*.<br/>
![Sloeber settings](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/SloeberDefineSymbols.png)
# 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.**<br/>
<br/>
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.
- Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc.
- Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 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
- ATmega8535, 16, 32, 164, 324, 644, 1284,
- ATmega64, 128
- ATmega4809 (Nano every)
- ATtiny3217 (Tiny Core 32 Dev Board)
- ATtiny84, 85, 167 (Digispark + Digispark Pro)
- SAMD (Zero, MKR*, **but not DUE, which is SAM architecture**)
- ESP32 (ESP32 C3 since board package 2.0.2 from Espressif)
- ESP8266 [This fork](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)
- 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.)
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.<br/>
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.
# 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.<br/>
Every pin can be used for receiving.
The MinimalReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer**.
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.<br/>
**Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.<br/>
| Board/CPU | Receive<br/>& PWM Timers| Hardware-PWM Pin | analogWrite()<br/>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** |
| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore) | **TCB0** | **PA05** |
| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore) | **TCA0**, TCD | % |
| [ATmega8](https://github.com/MCUdude/MiniCore) | **1** | **9** |
| 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 |
| [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 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://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 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin |
The **send PWM signal** is by default generated by software. **Therefore every pin can be used for sending**.
The PWM pulse length is guaranteed to be constant by using `delayMicroseconds()`.
Take care not to generate interrupts during sending with software generated PWM, otherwise you will get jitter in the generated PWM.
E.g. wait for a former `Serial.print()` statement to be finished by `Serial.flush()`.
Since the Arduino `micros()` function has a resolution of 4 µs at 16 MHz, we always see a small jitter in the signal, which seems to be OK for the receivers.
| Software generated PWM showing small jitter because of the limited resolution of 4 µs of the Arduino core `micros()` function for an ATmega328 | Detail (ATmega328 generated) showing 30% duty cycle |
|-|-|
| ![Software PWM](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_jitter.png) | ![Software PWM detail](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_PWM_by_software_detail.png) |
## 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.
The best approach is to change the timer used for IRremote, which can be accomplished by modifying the timer selection in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp).<br/>
For the AVR platform the code to modify looks like:
```c++
// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
# if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4) && !defined(IR_USE_AVR_TIMER5)
//#define IR_USE_AVR_TIMER1 // send pin = pin 11
#define IR_USE_AVR_TIMER2 // send pin = pin 9
//#define IR_USE_AVR_TIMER3 // send pin = pin 5
//#define IR_USE_AVR_TIMER4 // send pin = pin 6
//#define IR_USE_AVR_TIMER5 // send pin = pin 46
# endif
```
You **just have to modify the comments** of the current and desired timer line.
But be aware that the new timer in turn might be incompatible with other libraries or commands.<br/>
The modification must be renewed for each new IRremote library version, or you use an IDE like [Sloeber](https://github.com/Arduino-IRremote/Arduino-IRremote#modifying-compile-options-with-sloeber-ide).<br/>
For other platforms you must modify the appropriate section guarded by e.g. `#elif defined(ESP32)`.
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)`.<br/>
This only works since 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. The same timer as for the receiver is used.
Since each hardware timer has its dedicated output pins, you must change timer to change PWM output.<br/>
## 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):
- 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.
Due to automatic gain control and other bias effects, high intensity of the 38 kHz pulse counts more than medium intensity (e.g. 50% duty cycle) at the same total energy.
## Increase sending power
**The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.1 to 1.5 volt so you can supply 3 diodes with a 5 volt output.<br/>
To keep the current for 2 diodes with 1.3 volt and 25 mA and a 5 volt supply, you must reduce the resistor by factor: (5V - 1.3V) / (5V - 2.6V) = 1.5 e.g. from 150 ohm to 100 ohm.<br/>
For 3 diodes it requires factor 2.5 e.g. from 150 ohm to 60 ohm.<br/>
Or compute it directly with the **U = R * I formula**. Here U is (5V - <number_of_diodes> * 1.3V) at moderate current, at higher currents you must choose more than 1.3 volt. If you want to be exact, you must check the datasheet of your diode for the appropriate **forward voltage fo a given current**.
# 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.<br/>
And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!<br/>
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).<br/>
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.<br/>
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 basics of **real world signal processing**.
# NEC encoding diagrams
Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.<br/>
8 bit address NEC code
![8 bit address NEC code](https://user-images.githubusercontent.com/6750655/108884951-78e42b80-7607-11eb-9513-b07173a169c0.png)
16 bit address NEC code
![16 bit address NEC code](https://user-images.githubusercontent.com/6750655/108885081-a6c97000-7607-11eb-8d35-274a7065b6c4.png)
# 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.<br/>
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.
| Subject | [IRMP](https://github.com/ukw100/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)<br/>**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [Minimal NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/MinimalReceiver) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
|---------|------|-----------|--------|----------|----------|----------|
| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC | 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 delayMicroseconds() | % | % |
| Send pins| All | All | All ? | Timer dependent | % | % |
| Decode method | OnTheFly | OnTheFly | RAM | RAM | OnTheFly | OnTheFly |
| Encode method | OnTheFly | OnTheFly | OnTheFly | OnTheFly or RAM | % | % |
| Callback suppport | x | % | % | % | x | % |
| Repeat handling | Receive + Send (partially) | % | ? | Receive + Send | Receive | Receive |
| LED feedback | x | % | x | x | x | % |
| FLASH usage (simple NEC example with 5 prints) | 1820<br/>(4300 for 15 main / 8000 for all 40 protocols)<br/>(+200 for callback)<br/>(+80 for interrupt at pin 2+3)| 1270<br/>(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? |
| RAM usage | 52<br/>(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 |
| Supported platforms | **avr, megaAVR, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3<br/>(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attachInterrupt()** | **All platforms with attachInterrupt()** |
| Last library update | 6/2022 | 4/2018 | 3/2022 | 6/2022 | 6/2022 | 2/2022 |
| Remarks | Decodes 40 protocols concurrently.<br/>39 Protocols to send.<br/>Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 45 issues, no reaction for at least one year.** | Decoding and sending are easy to extend.<br/>Supports **Pronto** codes. | 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
# Revision History
Please see [changelog.md](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md).
# Contributing
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell other people about this library
- Contribute new protocols
Check [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributing.md) for some guidelines.
## Adding new protocols
To add a new protocol is quite straightforward. Best is too look at the existing protocols to find a similar one and modify it.<br/>
As a rule of thumb, it is easier to work with a description of the protocol rather than trying to entirely reverse-engineer the protocol.
Please include a link to the description in the header, if you found one.<br/>
The **durations** you receive are likely to be longer for marks and shorter for spaces than the protocol suggests,
but this depends on the receiver circuit in use. Most protocols use multiples of one time-unit for marks and spaces like e.g. [NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L62). It's easy to be off-by-one with the last bit, since the last space is not recorded by IRremote.
Try to make use of the template functions `decodePulseDistanceData()` and `sendPulseDistanceData()`.
If your protocol supports address and code fields, try to reflect this in your api like it is done in [`sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L96)
and [`decodeNEC()`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_NEC.hpp#L194).<br/>
### Integration
To integrate your protocol, you need to extend the two functions `decode()` and `getProtocolString()` in *IRreceice.hpp*,
add macros and function declarations for sending and receiving and extend the `enum decode_type_t` in *IRremote.h*.<br/>
And at least it would be wonderful if you can provide an example how to use the new protocol.
A detailed description can be found in the [ir_Template.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Template.hpp#L11) file.
### Creating API documentation
To generate the API documentation, Doxygen, as well as [Graphviz](http://www.graphviz.org/) should be installed.
(Note that on Windows, it is useful to specify the installer to add Graphviz to PATH or to do it manually.
With Doxygen and Graphviz installed, issue the command
`doxygen` from the command line in the main project directory, which will
generate the API documentation in HTML format.
The just generated `docs/index.html` can now be opened in a browser.
## Contributors
Check [here](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<br/>
Copyright (c) 2016-2017 Rafi Khan<br/>
Copyright (c) 2020-2022 [Armin Joachimsmeyer](https://github.com/ArminJo)

View File

@@ -0,0 +1,272 @@
# Changelog
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
## 3.7.2
- No reference found for Samsung "repeats are like NEC but with 2 stop bits", so changed to observed regular behavior.
## 3.7.1
- SendRaw now supports bufferlenght > 255.
- Improved DistanceProtocol decoder output.
- Fixed ESP32 send bug for 2.x ESP32 cores.
## 3.7.0
- Changed TOLERANCE to TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING and documented it.
- Changed last uint8_t to uint_fast8_t and uint16_t to unsigned integer.
- Improved MagiQuest protocol.
- Improved prints and documentation.
- Added IrReceiver.restartAfterSend() and inserted it in every send(). Closes #989
- Use IRAM_ATTR instead of deprecated ICACHE_RAM_ATTR for ESP8266.
- Removed pulse width decoding from ir_DistanceProtocol.
## 3.6.1
- Switched Bose internal protocol timing for 0 and 1 -> old 1 timing is now 0 and vice versa.
## 3.6.0
- Separated enable flag of send and receive feedback LED. Inspired by PR#970 from luvaihassanali.
- RP2040 support added.
- Refactored IRTimer.hpp.
- Refactored IR_SEND_PIN and IrSender.sendPin handling.
- Renamed IR_SEND_DUTY_CYCLE to IR_SEND_DUTY_CYCLE_PERCENT.
- Fixed bugs for SEND_PWM_BY_TIMER active.
## 3.5.2
- Improved support for Teensy boards by Paul Stoffregen.
## 3.5.1
- Renamed INFO_PRINT to IR_INFO_PRINT as well as for DEBUG and TRACE.
- Fixed error with DEBUG in TinyIRReceiver.hpp.
- Support for ATmega88 see issue #923. Thanks to Dolmant.
- NO_LED_FEEDBACK_CODE replaces and extends DISABLE_LED_FEEDBACK_FOR_RECEIVE.
- Removed NO_LEGACY_COMPATIBILITY macro, it was useless now.
- Fix ESP32 send bug see issue #927.
## 3.5.0
- Improved ir_DistanceProtocol.
- Tone for ESP32.
- last phase renamed *.cpp.h to .hpp.
- No deprecation print for ATtinies.
- Renamed ac_LG.cpp to ac_LG.hpp.
- Maintained MagiQuest by E. Stuart Hicks.
- Improved print Pronto by Asuki Kono.
- Added printActiveIRProtocols() function.
- Used IR_SEND_PIN to reduce code size and improved send timing for AVR.
## 3.4.0
- Added LG2 protocol.
- Added ATtiny167 (Digispark Pro) support.
- Renamed *.cpp.h to .hpp.
- organized carrier frequencies.
- Compiler switch USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN added.
- Moved blink13() back to IRrecv class.
- Added Kaseikyo convenience functions like sendKaseikyo_Denon().
- Improved / adjusted LG protocol and added class Aircondition_LG based on real hardware supplied by makerspace 201 (https://wiki.hackerspaces.org/ZwoNullEins) from Cologne.
- Improved universal decoder for pulse distance protocols to support more than 32 bits.
- Added mbed support.
## 3.3.0
- Fix errors if LED_BUILTIN is not defined.
- Fixed error for AVR timer1. Thanks to alexbarcelo.
- New example IRremoteExtensionTest.
- Enabled megaAVR 0-series devices.
- Added universal decoder for pulse distance protocols.
## 3.2.0
- Fix for ESP32 send Error, removed `USE_SOFT_SEND_PWM` macro.
- Added Onkyo protocol.
- Support for old 2.x code by backwards compatible `decode(decode_results *aResults)` function.
- Removed USE_OLD_DECODE macro and added NO_LEGACY_COMPATIBILITY macro.
- Added ATtiny1604 support.
- New SendAndReceive example.
- Added ESP8266 support.
- Extended DEBUG output.
## 3.1.0
- Generation of PWM by software is active by default.
- Removed decode_results results.
- Renamed most irparams_struct values.
- Fixed LG send bug and added unit test.
- Replaced `#define DECODE_NEC 1/0` by defining/not defining.
- Use LED_BUILTIN instead of FEEDBACK_LED if FeedbackLEDPin is 0.
- Use F_CPU instead of SYSCLOCK.
- Removed SENDPIN_ON and SENDPIN_OFF macros.
- Refactored board specific code for timer and feedback LED.
- Extracted common LED feedback functions and implemented feedback for send.
- MATCH_MARK() etc. now available as matchMark().
- Added STM32F1 by (by Roger Clark) support.
- Added stm32 (by ST) support. Thanks to Paolo Malaspina.
- Added ATtiny88 support.
## 3.0.2
- Bug fix for USE_OLD_DECODE.
- Increase RECORD_GAP_MICROS to 11000.
- Fix overflow message. (#793).
- Improved handling for HASH decoder.
- Tested for ATtiny85.
- Added `printIRResultMinimal()`.
- Added missing IRAM_ATTR for ESP32.
- Adapted to TinyCore 0.0.7.
- Fixed decodeSony 20 bit bug #811.
- Replaced delayMicroseconds with customDelayMicroseconds and removed NoInterrupt() for send functions, removed SPIN_WAIT macro, sleepMicros() and sleepUntilMicros().
- Fixed LG checksum error.
- Fixed JVC repeat error.
## 3.0.0 + 3.0.1 2021/02
- New LSB first decoders are default.
- Added SendRaw with byte data.
- Fixed resume bug if irparams.rawlen >= RAW_BUFFER_LENGTH. Thanks to Iosif Peterfi
- Added `dumpPronto(String *aString, unsigned int frequency)` with String object as argument. Thanks to Iosif Peterfi
- Removed Test2 example.
- Fixed swapped cases in `getProtocolString()`. Thanks to Jim-2249
- Added compile option `IR_INPUT_IS_ACTIVE_HIGH`. Thanks to Jim-2249
- Corrected template. Thanks to Jim-2249
- Introduced standard decode and send functions.
- Added compatibility with tone for AVR's.
- New TinyIRreceiver does not require a timer.
- New MinimalReceiver and IRDispatcherDemo examples.
- Added TinyCore 32 / ATtiny3217 support.
- Added Apple protocol.
## 2.8.1 2020/10
- Fixed bug in Sony decode introduced in 2.8.0.
## 2.8.0 2020/10
- Changed License to MIT see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/397.
- Added ATtiny timer 1 support.
- Changed wrong return code signature of decodePulseDistanceData() and its handling.
- Removed Mitsubishi protocol, since the implementation is in contradiction with all documentation I found and therefore supposed to be wrong.
- Removed AIWA implementation, since it is only for 1 device and at least the sending was implemented wrong.
- Added Lego_PF decode.
- Changed internal usage of custom_delay_usec.
- Moved dump/print functions from example to irReceiver.
- irPronto.cpp: Using Print instead of Stream saves 1020 bytes program memory. Changed from & to * parameter type to be more transparent and consistent with other code of IRremote.
## 2.7.0 2020/09
- Added ATmega328PB support.
- Renamed hardware specific macro and function names.
- Renamed `USE_SOFT_CARRIER`, `USE_NO_CARRIER`, `DUTY_CYCLE` macros to `USE_SOFT_SEND_PWM`, `USE_NO_SEND_PWM`, `IR_SEND_DUTY_CYCLE`.
- Removed blocking wait for ATmega32U4 Serial in examples.
- Deactivated default debug output.
- Optimized types in sendRC5ext and sendSharpAlt.
- Added `DECODE_NEC_STANDARD` and `SEND_NEC_STANDARD`.
- Renamed all IRrecv* examples to IRreceive*.
- Added functions `printIRResultShort(&Serial)` and `getProtocolString(decode_type_t aDecodeType)`.
- Added flag `decodedIRData.isRepeat`.
- Updated examples.
## 2.6.1 2020/08
- Adjusted JVC and LG timing.
- Fixed 4809 bug.
## 2.6.0 2020/08
- Added support for MagiQuest IR wands.
- Corrected Samsung timing.
- NEC repeat implementation.
- Formatting and changing `TIMER_CONFIG_KHZ` and `TIMER_CONFIG_NORMAL` macros to static functions.
- Added `IRAM_ATTR` for ESP32 ISR.
- Removed `#define HAS_AVR_INTERRUPT_H`.
- Changed Receiver States. Now starting with 0.
- Changed switch to if / else if in IRRemote.cpp because of ESP32 compiler bug.
- Changed `DEBUG` handling since compiler warns about empty "IF" or "ELSE" statements in IRRemote.cpp.
## 2.5.0 2020/06
- 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 `SEND_PIN` to `IR_SEND_PIN`.
- Renamed state macros.
- Enabled `DUTY_CYCLE` for send signal.
- Added sending for ESP32.
- Changed rawlen from uint8_t to unsigned int allowing bigger receive buffer and renamed `RAWBUF` to `RAW_BUFFER_LENGTH`.
- Introduced `USE_NO_CARRIER` for simulating an IR receiver.
Changes from #283 by bengtmartensson
- Added function sendRaw_P() for sending data from flash.
Changes from #268 by adamlhumphreys
- Optimized by reducing floating point operations as suggested by madmalkav (#193).
- Optimized with macros when using default `MICROS_PER_TICK` and `TOLERANCE`.
- Made decodeHash as a settable protocol defined by `DECODE_HASH`.
- Added Philips Extended RC-5 protocol support [PR #522] (https://github.com/Arduino-IRremote/Arduino-IRremote/pull/522)
## 2.4.0 - 2017/08/10
- Cleanup of hardware dependencies. Merge in SAM support [PR #437](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/437)
## 2.3.3 - 2017/03/31
- Added ESP32 IR receive support [PR #427](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/425)
## 2.2.3 - 2017/03/27
- Fix calculation of pause length in LEGO PF protocol [PR #427](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/427)
## 2.2.2 - 2017/01/20
- Fixed naming bug [PR #398](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/398)
## 2.2.1 - 2016/07/27
- Added tests for Lego Power Functions Protocol [PR #336](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/336)
## 2.2.0 - 2016/06/28
- Added support for ATmega8535
- Added support for ATmega16
- Added support for ATmega32
- Added support for ATmega164
- Added support for ATmega324
- Added support for ATmega644
- Added support for ATmega1284
- Added support for ATmega64
- Added support for ATmega128
[PR](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/324)
## 2.1.1 - 2016/05/04
- Added Lego Power Functions Protocol [PR #309](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/309)
## 2.1.0 - 2016/02/20
- Improved Debugging [PR #258](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/258)
- Display TIME instead of TICKS [PR #258](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/258)
## 2.0.4 - 2016/02/20
- Add Panasonic and JVC to IRrecord example [PR](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/54)
## 2.0.3 - 2016/02/20
- Change IRSend Raw parameter to const [PR](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/227)
## 2.0.2 - 2015/12/02
- Added IRremoteInfo Sketch - [PR](https://github.com/Arduino-IRremote/Arduino-IRremote/pull/241)
- Enforcing changelog.md
## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA)
### Changes
- Updated README
- Updated Contributors
- Fixed #110 Mess
- Created Gitter Room
- Added Gitter Badge
- Standardised Code Base
- Clean Debug Output
- Optimized Send Loops
- Modularized Design
- Optimized and Updated Examples
- Improved Documentation
- Fixed and Improved many coding errors
- Fixed Aiwa RC-T501 Decoding
- Fixed Interrupt on ATmega8
- Switched to Stable Release of PlatformIO
### Additions
- Added Aiwa RC-T501 Protocol
- Added Denon Protocol
- Added Pronto Support
- Added compile options
- Added Template For New Protocols
- Added this changelog
- Added Teensy LC Support
- Added ATtiny84 Support
- Added ATtiny85 Support
- Added isIdle method
### Deletions
- Removed (Fixed) #110
- Broke Teensy 3 / 3.1 Support
### Not Working
- Teensy 3 / 3.1 Support is in Development

View File

@@ -0,0 +1,103 @@
/*
* ControlRelay.cpp
*
* Toggles an output pin at each command received
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Initially coded 2009 Ken Shirriff http://www.righto.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2021 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
* 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 <Arduino.h>
#if FLASHEND <= 0x1FFF // For 8k flash or less, like ATtiny85. Exclude exotic protocols.
#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
#define EXCLUDE_EXOTIC_PROTOCOLS
#endif
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#if defined(APPLICATION_PIN)
#define RELAY_PIN APPLICATION_PIN
#else
#define RELAY_PIN 5
#endif
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
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)
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 IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}
int on = 0;
unsigned long last = millis();
void loop() {
if (IrReceiver.decode()) {
// If it's been at least 1/4 second since the last
// IR received, toggle the relay
if (millis() - last > 250) {
on = !on;
Serial.print(F("Switch relay "));
if (on) {
digitalWrite(RELAY_PIN, HIGH);
Serial.println(F("on"));
} else {
digitalWrite(RELAY_PIN, LOW);
Serial.println(F("off"));
}
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
IrReceiver.printIRResultShort(&Serial);
Serial.println();
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#else
// Print a minimal summary of received data
IrReceiver.printIRResultMinimal(&Serial);
Serial.println();
#endif // FLASHEND
}
last = millis();
IrReceiver.resume(); // Enable receiving of the next value
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,107 @@
/*
* 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/ukw100/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 <http://www.gnu.org/licenses/gpl.html>.
*/
#ifndef _IR_COMMAND_DISPATCHER_H
#define _IR_COMMAND_DISPATCHER_H
#include <stdint.h>
/*
* 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 / non regular) (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)
/*
* if this command is received, requestToStopReceived is set until call of next loop.
* This stops ongoing commands which use: RDispatcher.delayAndCheckForStop(100); RETURN_IF_STOP;
*/
#define IR_COMMAND_FLAG_IS_STOP_COMMAND 0x04 // sets requestToStopReceived (to stop other commands)
// Basic mapping structure
struct IRToCommandMappingStruct {
uint8_t IRCode;
uint8_t Flags;
void (*CommandToCall)();
const char *CommandString;
};
struct IRDataForCommandDispatcherStruct {
uint16_t address; // to distinguish between multiple senders
uint16_t command;
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.
};
/*
* Special codes (hopefully) not sent by the remote - otherwise please redefine it here
*/
#define COMMAND_EMPTY 0xFE // code no command received
#define COMMAND_INVALID 0xFF // code for command received, but not in mapping
#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();
bool delayAndCheckForStop(uint16_t aDelayMillis);
// The main dispatcher function
void checkAndCallCommand(bool aCallAlsoBlockingCommands);
void printIRCommandString(Print *aSerial);
void setRequestToStopReceived();
uint8_t currentBlockingCommandCalled = COMMAND_INVALID; // The code for the current called command
bool executingBlockingCommand = false; // Lock for recursive calls of regular commands
bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command
uint8_t BlockingCommandToRunNext = COMMAND_INVALID; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
/*
* Flag for running blocking commands to terminate. To check, you can use "if (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;
/*
* If we have a function, which want to interpret the IR codes by itself e.g. the calibrate function if QuadrupedControl then this flag must be true
*/
bool doNotUseDispatcher = false;
struct IRDataForCommandDispatcherStruct IRReceivedData;
};
extern IRCommandDispatcher IRDispatcher;
#endif // _IR_COMMAND_DISPATCHER_H

View File

@@ -0,0 +1,329 @@
/*
* 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 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-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/ukw100/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 <http://www.gnu.org/licenses/gpl.html>.
*/
#ifndef _IR_COMMAND_DISPATCHER_HPP
#define _IR_COMMAND_DISPATCHER_HPP
#include <Arduino.h>
#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(ESP32) || defined(ESP8266)
void IRAM_ATTR handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat)
# else
void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat)
# endif
{
IRDispatcher.IRReceivedData.address = aAddress;
IRDispatcher.IRReceivedData.command = aCommand;
IRDispatcher.IRReceivedData.isRepeat = isRepeat;
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 (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) {
IRDispatcher.checkAndCallCommand(false); // only short commands are executed directly
}
} 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 is called if a complete command was received
*/
#if defined(ESP32) || defined(ESP8266)
void IRAM_ATTR handleReceivedIRData()
#else
void handleReceivedIRData()
#endif
{
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
/*
* The main dispatcher function
* Sets flags justCalledRegularIRCommand, executingBlockingCommand
*/
void IRCommandDispatcher::checkAndCallCommand(bool aCallAlsoBlockingCommands) {
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<const __FlashStringHelper*>(IRMapping[i].CommandString);
#endif
/*
* Check for repeat and if it 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;
}
/*
* Handle stop commands
*/
if (IRMapping[i].Flags & IR_COMMAND_FLAG_IS_STOP_COMMAND) {
requestToStopReceived = true;
CD_INFO_PRINTLN(F("Stop command received"));
} else {
// 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 (!aCallAlsoBlockingCommands) {
/*
* Store for main loop to execute
*/
BlockingCommandToRunNext = IRReceivedData.command;
requestToStopReceived = true; // to stop running command
CD_INFO_PRINT(F("Blocking command "));
CD_INFO_PRINT (tCommandName);
CD_INFO_PRINTLN(F(" stored as next command and requested stop"));
} else {
if (executingBlockingCommand) {
// Logical error has happened
CD_INFO_PRINTLN(
F("Request to execute blocking command while another command is running. This should not happen!"));
/*
* A blocking command may not be called as long as another blocking command is running.
* Try to stop again
*/
BlockingCommandToRunNext = IRReceivedData.command;
requestToStopReceived = true; // to stop running command
return;
}
/*
* here we are called from main loop and execute a command
*/
justCalledBlockingCommand = true;
executingBlockingCommand = true; // set lock for recursive calls
currentBlockingCommandCalled = IRReceivedData.command;
/*
* 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
executingBlockingCommand = false;
currentBlockingCommandCalled = COMMAND_INVALID;
}
}
break; // command found
}
} // for loop
return;
}
/*
* 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 (IRDispatcher.requestToStopReceived) {
return true;
}
} while (millis() - tStartMillis < aDelayMillis);
return false;
}
/*
* 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_INVALID) {
CD_INFO_PRINT(F("Take stored command = 0x"));
CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX);
IRReceivedData.command = BlockingCommandToRunNext;
BlockingCommandToRunNext = COMMAND_INVALID;
IRReceivedData.isRepeat = false;
checkAndCallCommand(true);
return true;
}
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<const __FlashStringHelper*>(IRMapping[i].CommandString));
return;
}
}
aSerial->println(reinterpret_cast<const __FlashStringHelper*>(unknown));
}
void IRCommandDispatcher::setRequestToStopReceived() {
requestToStopReceived = true;
}
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#if defined(LOCAL_INFO)
#undef LOCAL_INFO
#endif
#endif // _IR_COMMAND_DISPATCHER_HPP

View File

@@ -0,0 +1,194 @@
/*
* IRCommandMapping.h
*
* IR remote button codes, strings, and functions to call
*
* Copyright (C) 2019-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
*/
#ifndef _IR_COMMAND_MAPPING_H
#define _IR_COMMAND_MAPPING_H
#include <Arduino.h>
//#include "Commands.h" // includes all the commands used in the mapping arrays below
/*
* !!! Choose your remote !!!
*/
//#define USE_KEYES_REMOTE_CLONE With number pad and direction control switched, will be taken as default
//#define USE_KEYES_REMOTE
#if !defined(USE_KEYES_REMOTE) && !defined(USE_KEYES_REMOTE_CLONE)
#define USE_KEYES_REMOTE_CLONE // the one you can buy at aliexpress
#endif
#if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE))
#error "Please choose only one remote for compile"
#endif
#if defined(USE_KEYES_REMOTE_CLONE)
#define IR_REMOTE_NAME "KEYES_CLONE"
// Codes for the KEYES CLONE remote control with 17 keys with number pad above direction control
#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
#define IR_RIGHT 0x5A
#define IR_LEFT 0x08
#define IR_OK 0x1C
#define IR_1 0x45
#define IR_2 0x46
#define IR_3 0x47
#define IR_4 0x44
#define IR_5 0x40
#define IR_6 0x43
#define IR_7 0x07
#define IR_8 0x15
#define IR_9 0x09
#define IR_0 0x19
#define IR_STAR 0x16
#define IR_HASH 0x0D
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_START IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_RESET IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE1 IR_1
#define COMMAND_TONE2 IR_2
#define COMMAND_TONE3 IR_3
//#define IR_4
//#define IR_5
//#define IR_6
//#define IR_7
//#define IR_8
//#define IR_9
#endif
#if defined(USE_KEYES_REMOTE)
#define IR_REMOTE_NAME "KEYES"
/*
* FIRST:
* IR code to button mapping for better reading. IR codes should only referenced here.
*/
// Codes for the KEYES remote control with 17 keys and direction control above number pad
#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
#define IR_RIGHT 0x43
#define IR_LEFT 0x44
#define IR_OK 0x40
#define IR_1 0x16
#define IR_2 0x19
#define IR_3 0x0D
#define IR_4 0x0C
#define IR_5 0x18
#define IR_6 0x5E
#define IR_7 0x08
#define IR_8 0x1C
#define IR_9 0x5A
#define IR_0 0x52
#define IR_STAR 0x42
#define IR_HASH 0x4A
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_RESET IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_STOP IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE2 IR_1
#define COMMAND_TONE1 IR_2
#define COMMAND_TONE2 IR_3
#define COMMAND_TONE2 IR_4
#define COMMAND_TONE2 IR_5
#define COMMAND_TONE2 IR_6
#define COMMAND_TONE2 IR_7
#define COMMAND_TONE2 IR_8
#define COMMAND_TONE2 IR_9
#endif
/*
* THIRD:
* Main mapping of commands to C functions
*/
// IR strings of functions for output
static const char LEDon[] PROGMEM ="LED on";
static const char LEDoff[] PROGMEM ="LED off";
static const char blink20times[] PROGMEM ="blink 20 times";
static const char blinkStart[] PROGMEM ="blink start";
static const char increaseBlink[] PROGMEM ="increase blink frequency";
static const char decreaseBlink[] PROGMEM ="decrease blink frequency";
static const char tone2200[] PROGMEM ="tone 2200";
static const char tone1800[] PROGMEM ="tone 1800";
static const char printMenu[] PROGMEM ="printMenu";
static const char reset[] PROGMEM ="reset";
static const char stop[] PROGMEM ="stop";
// 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
*/
const struct IRToCommandMappingStruct IRMapping[] =
{
{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING, &doLedBlink20times, blink20times },
/*
* Short commands, which can be executed always
*/
{ 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_STOP, IR_COMMAND_FLAG_IS_STOP_COMMAND, &doStop, stop },
/*
* 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 } };
#endif // _IR_COMMAND_MAPPING_H

View File

@@ -0,0 +1,286 @@
/*
* IRDispatcherDemo.cpp
*
* Receives NEC IR commands and maps them to different actions by means of a mapping array.
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#include <Arduino.h>
/*
* Choose the library to be used for IR receiving
*/
#define USE_TINY_IR_RECEIVER // Recommended, 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 // costs 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
#endif
#define IR_INPUT_PIN 2
//#define NO_LED_FEEDBACK_CODE // You can set it here, before the include of IRCommandDispatcher below
#if defined(USE_TINY_IR_RECEIVER) && !defined(IR_INPUT_PIN)
#if defined(IR_RECEIVE_PIN)
#define IR_INPUT_PIN IR_RECEIVE_PIN // The pin where the IR input signal is expected. The pin must be capable of generating a pin change interrupt.
#endif
#if defined(IRMP_INPUT_PIN)
#define IR_INPUT_PIN IRMP_INPUT_PIN // The pin where the IR input signal is expected. The pin must be capable of generating a pin change interrupt.
#endif
#elif defined(USE_IRMP_LIBRARY)
/*
* IRMP version
*/
#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
#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 <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 <irmp.hpp>
void handleReceivedIRData();
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration);
#endif // #if defined(USE_IRMP_LIBRARY)
bool doBlink = false;
uint16_t sBlinkDelay = 200;
void doPrintMenu();
void doLedOn();
void doLedOff();
void doIncreaseBlinkFrequency();
void doDecreaseBlinkFrequency();
void doStop();
void doResetBlinkFrequency();
void doLedBlinkStart();
void doLedBlink20times();
void doTone1800();
void doTone2200();
/*
* Set definitions and include IRCommandDispatcher library after the declaration of all commands to map
*/
#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 "IRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown".
#include "IRCommandDispatcher.hpp"
/*
* Helper macro for getting a macro definition as string
*/
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
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!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver"));
#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
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
Serial.print(F("Listening to commands of IR remote of type "));
Serial.println(IR_REMOTE_NAME);
doPrintMenu();
}
void loop() {
IRDispatcher.checkAndRunSuspendedBlockingCommands();
if (doBlink) {
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
}
if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000)
{
//Short beep as remainder, if we did not receive any command in the last 2 minutes
IRDispatcher.IRReceivedData.MillisOfLastCode += 120000;
doTone1800();
}
// delay(10);
}
void doPrintMenu(){
Serial.println();
Serial.println(F("Press 1 for tone 1800 Hz"));
Serial.println(F("Press 2 for tone 2200 Hz"));
Serial.println(F("Press 3 for this Menu"));
Serial.println(F("Press 0 for LED blink 20 times"));
Serial.println(F("Press UP for LED on"));
Serial.println(F("Press DOWN for LED off"));
Serial.println(F("Press OK for LED blink start"));
Serial.println(F("Press RIGHT for LED increase blink frequency"));
Serial.println(F("Press LEFT for LED decrease blink frequency"));
Serial.println(F("Press STAR for reset blink frequency"));
Serial.println(F("Press HASH for stop"));
Serial.println();
}
/*
* Here the actions that are matched to IR keys
*/
void doLedOn() {
digitalWrite(LED_BUILTIN, HIGH);
doBlink = false;
}
void doLedOff() {
digitalWrite(LED_BUILTIN, LOW);
doBlink = false;
}
void doIncreaseBlinkFrequency() {
doBlink = true;
if (sBlinkDelay > 5) {
sBlinkDelay -= sBlinkDelay / 4;
}
}
void doDecreaseBlinkFrequency() {
doBlink = true;
sBlinkDelay += sBlinkDelay / 4;
}
void doStop() {
doBlink = false;
}
void doResetBlinkFrequency() {
sBlinkDelay = 200;
digitalWrite(LED_BUILTIN, LOW);
}
void doLedBlinkStart() {
doBlink = true;
}
/*
* This is a blocking function and checks periodically 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);
}
}
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
#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
#endif
}
#if defined(USE_IRMP_LIBRARY)
/*
* Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated
* It currently disables the receiving of repeats
*/
void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
# if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
storeIRTimer();
tone(_pin, frequency, 0);
if (duration == 0) {
duration = 100;
}
delay(duration);
noTone(_pin);
restoreIRTimer();
#elif defined(ESP8266)
// tone() stops timer 1
(void) _pin;
(void) frequency;
(void) duration;
#else
tone(_pin, frequency, duration);
#endif
}
#endif // #if defined(USE_IRMP_LIBRARY)

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,42 @@
/*
* IRremoteExtensionClass.cpp
*
* Example for a class which itself uses the IRrecv class from IRremote
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2021 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 <Arduino.h>
#include "IRremoteExtensionClass.h"
IRExtensionClass::IRExtensionClass(IRrecv *aIrReceiver) {
MyIrReceiver = aIrReceiver;
}
void IRExtensionClass::resume() {
Serial.println(F("Call resume()"));
MyIrReceiver->resume();
}

View File

@@ -0,0 +1,44 @@
/*
* IRremoteExtensionClass.h
*
* Example for a class which itself uses the IRrecv class from IRremote
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2021 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 <Arduino.h>
#define USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE
#include <IRremote.hpp>
class IRExtensionClass
{
public:
IRrecv * MyIrReceiver;
IRExtensionClass(IRrecv * aIrReceiver);
void resume();
};

View File

@@ -0,0 +1,43 @@
/*
* IRremoteExtensionTest.cpp
* Simple test using the IRremoteExtensionClass.
*/
#include <Arduino.h>
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#include "IRremoteExtensionClass.h"
/*
* Create the class, which itself uses the IRrecv class from IRremote
*/
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!
#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 IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}
void loop() {
if (IrReceiver.decode()) {
IrReceiver.printIRResultShort(&Serial);
IRExtension.resume(); // Use the extended function
}
delay(100);
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,349 @@
/*
* IRremote: IRremoteInfo - prints relevant config info & settings for IRremote over serial
* Intended to help identify & troubleshoot the various settings of IRremote
* For example, sometimes users are unsure of which pin is used for Tx or the RAW_BUFFER_LENGTH value
* This example can be used to assist the user directly or with support.
* Intended to help identify & troubleshoot the various settings of IRremote
* Hopefully this utility will be a useful tool for support & troubleshooting for IRremote
* Check out the blog post describing the sketch via http://www.analysir.com/blog/2015/11/28/helper-utility-for-troubleshooting-irremote/
* Version 1.0 November 2015
* Original Author: AnalysIR - IR software & modules for Makers & Pros, visit http://www.AnalysIR.com
*/
#include <Arduino.h>
//#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
//#define NO_LED_FEEDBACK_CODE // saves 566 bytes program memory
#include <IRremote.hpp>
// Function declarations for non Arduino IDE's
void dumpHeader();
void dumpRAW_BUFFER_LENGTH();
void dumpTIMER();
void dumpTimerPin();
void dumpClock();
void dumpPlatform();
void dumpPulseParams();
void dumpSignalParams();
void dumpArduinoIDE();
void dumpDebugMode();
void dumpProtocols();
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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
//Runs only once per restart of the Arduino.
dumpHeader();
dumpRAW_BUFFER_LENGTH();
dumpTIMER();
dumpTimerPin();
dumpClock();
dumpPlatform();
dumpPulseParams();
dumpSignalParams();
dumpArduinoIDE();
dumpDebugMode();
dumpProtocols();
dumpFooter();
}
void loop() {
//nothing to do!
}
void dumpRAW_BUFFER_LENGTH() {
Serial.print(F("RAW_BUFFER_LENGTH: "));
Serial.println(RAW_BUFFER_LENGTH);
}
void dumpTIMER() {
bool flag = false;
#if defined(IR_USE_TIMER1)
Serial.print(F("Timer defined for use: "));
Serial.println(F("Timer1"));
flag = true;
#endif
#if defined(IR_USE_TIMER2)
Serial.print(F("Timer defined for use: "));
Serial.println(F("Timer2"));
flag = true;
#endif
#if defined(IR_USE_TIMER3)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer3")); flag = true;
#endif
#if defined(IR_USE_TIMER4)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer4")); flag = true;
#endif
#if defined(IR_USE_TIMER5)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer5")); flag = true;
#endif
#if defined(IR_USE_TIMER4_HS)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer4_HS")); flag = true;
#endif
#if defined(IR_USE_TIMER_CMT)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_CMT")); flag = true;
#endif
#if defined(IR_USE_TIMER_TPM1)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_TPM1")); flag = true;
#endif
#if defined(IR_USE_TIMER_TINY0)
Serial.print(F("Timer defined for use: ")); Serial.println(F("Timer_TINY0")); flag = true;
#endif
if (!flag) {
Serial.print(F("Timer Error: "));
Serial.println(F("not defined"));
}
}
void dumpTimerPin() {
Serial.print(F("IR Send Pin: "));
#if defined(IR_SEND_PIN)
Serial.println(IR_SEND_PIN);
#else
Serial.println(IrSender.sendPin);
#endif
}
void dumpClock() {
#if defined(F_CPU)
Serial.print(F("MCU Clock: "));
Serial.println(F_CPU);
#endif
}
void dumpPlatform() {
Serial.print(F("MCU Platform: "));
#if defined(__AVR_ATmega8__)
Serial.println(F("Atmega8"));
#elif defined(__AVR_ATmega16__)
Serial.println(F("ATmega16"));
#elif defined(__AVR_ATmega32__)
Serial.println(F("ATmega32"));
#elif defined(__AVR_ATmega32U4__)
Serial.println(F("Arduino Leonardo / Yun / Teensy 1.0 / ATmega32U4"));
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__)
Serial.println(F("ATmega48"));
#elif defined(__AVR_ATmega64__)
Serial.println(F("ATmega64"));
#elif defined(__AVR_ATmega88__) || defined(__AVR_ATmega88P__)
Serial.println(F("ATmega88"));
#elif defined(__AVR_ATmega162__)
Serial.println(F("ATmega162"));
#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__)
Serial.println(F("ATmega164"));
#elif defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__)
Serial.println(F("ATmega324"));
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__)
Serial.println(F("ATmega644"));
#elif defined(__AVR_ATmega1280__)
Serial.println(F("Arduino Mega1280"));
#elif defined(__AVR_ATmega1281__)
Serial.println(F("ATmega1281"));
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
Serial.println(F("ATmega1284"));
#elif defined(__AVR_ATmega2560__)
Serial.println(F("Arduino Mega2560"));
#elif defined(__AVR_ATmega2561__)
Serial.println(F("ATmega2561"));
#elif defined(__AVR_ATmega8515__)
Serial.println(F("ATmega8515"));
#elif defined(__AVR_ATmega8535__)
Serial.println(F("ATmega8535"));
#elif defined(__AVR_AT90USB162__)
Serial.println(F("Teensy 1.0 / AT90USB162"));
// Teensy 2.0
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
Serial.println(F("Teensy 3.0 / Teensy 3.1 / MK20DX128 / MK20DX256"));
#elif defined(__MKL26Z64__)
Serial.println(F("Teensy-LC / MKL26Z64"));
#elif defined(__AVR_AT90USB646__)
Serial.println(F("Teensy++ 1.0 / AT90USB646"));
#elif defined(__AVR_AT90USB1286__)
Serial.println(F("Teensy++ 2.0 / AT90USB1286"));
#elif defined(__AVR_ATtiny84__)
Serial.println(F("ATtiny84"));
#elif defined(__AVR_ATtiny85__)
Serial.println(F("ATtiny85"));
#else
Serial.println(F("ATmega328(P) / (Duemilanove, Diecimila, LilyPad, Mini, Micro, Fio, Nano, etc)"));
#endif
}
void dumpPulseParams() {
Serial.print(F("Mark Excess: "));
Serial.print(MARK_EXCESS_MICROS);
;
Serial.println(F(" uSecs"));
Serial.print(F("Microseconds per tick: "));
Serial.print(MICROS_PER_TICK);
;
Serial.println(F(" uSecs"));
Serial.print(F("Measurement tolerance: "));
Serial.print(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING);
Serial.println(F("%"));
}
void dumpSignalParams() {
Serial.print(F("Minimum Gap between IR Signals: "));
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" uSecs"));
}
void dumpDebugMode() {
Serial.print(F("Debug Mode: "));
#if DEBUG
Serial.println(F("ON"));
#else
Serial.println(F("OFF (Normal)"));
#endif
}
void dumpArduinoIDE() {
Serial.print(F("Arduino IDE version: "));
Serial.print(ARDUINO / 10000);
Serial.write('.');
Serial.print((ARDUINO % 10000) / 100);
Serial.write('.');
Serial.println(ARDUINO % 100);
}
void dumpProtocols() {
Serial.println();
Serial.print(F("IR PROTOCOLS "));
Serial.print(F("SEND "));
Serial.println(F("DECODE"));
Serial.print(F("============= "));
Serial.print(F("======== "));
Serial.println(F("========"));
Serial.print(F("RC5: "));
#if defined(DECODE_RC5)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("RC6: "));
#if defined(DECODE_RC6)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("NEC: "));
#if defined(DECODE_NEC)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("SONY: "));
#if defined(DECODE_SONY)
Serial.println(F("Enabled"));
#else
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"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("SAMSUNG: "));
#if defined(DECODE_SAMSUNG)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("LG: "));
#if defined(DECODE_LG)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("DENON: "));
#if defined(DECODE_DENON)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory
Serial.print(F("BOSEWAVE: "));
#if defined(DECODE_BOSEWAVE)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
Serial.print(F("WHYNTER: "));
#if defined(DECODE_WHYNTER)
Serial.println(F("Enabled"));
#else
Serial.println(F("Disabled"));
#endif
#endif
}
void printDecodeEnabled(int flag) {
if (flag) {
Serial.println(F("Enabled"));
} else {
Serial.println(F("Disabled"));
}
}
void dumpHeader() {
Serial.println(F("IRremoteInfo - by AnalysIR (http://www.AnalysIR.com/)"));
Serial.println(
F(
"- A helper sketch to assist in troubleshooting issues with the library by reviewing the settings within the IRremote library"));
Serial.println(
F(
"- Prints out the important settings within the library, which can be configured to suit the many supported platforms"));
Serial.println(F("- When seeking on-line support, please post or upload the output of this sketch, where appropriate"));
Serial.println();
Serial.println(F("IRremote Library Settings"));
Serial.println(F("========================="));
}
void dumpFooter() {
Serial.println();
Serial.println(F("Notes: "));
Serial.println(F("- Most of the settings above can be configured in the following files included as part of the library"));
Serial.println(F("- IRremoteInt.h"));
Serial.println(F("- IRremote.h"));
Serial.println(
F("- You can save SRAM by disabling the Decode or Send features for any protocol (Near the top of IRremoteInt.h)"));
Serial.println(
F(
"- Some Timer conflicts, with other libraries, can be easily resolved by configuring a different Timer for your platform"));
}

View File

@@ -0,0 +1,388 @@
/**
* @file MicroGirs.ino
*
* @brief This is a minimalistic <a href="http://harctoolbox.org/Girs.html">Girs server</a>.
* It only depends on (a subset of) IRremote. It can be used with
* <a href="http://www.harctoolbox.org/IrScrutinizer.html">IrScrutinizer</a>
* (select Sending/Capturing hw = Girs Client) as well as
* <a href="http://lirc.org">Lirc</a>
* version 0.9.4 and later, using the driver <a href="http://lirc.org/html/girs.html">Girs</a>).
* (Authors of similar software are encourage to implement support.)
*
* It runs on all hardware on which IRemote runs.
*
* It consists of an interactive IR server, taking one-line commands from
* the "user" (which is typically not a person but another program), and
* responds with a one-line response. In the language of the Girs
* specifications, the modules "base", receive, and transmit are
* implemented. (The two latter can be disabled by not defining two
* corresponding CPP symbols.)
*
* It understands the following commands:
*
* The "version" command returns the program name and version,
* The "modules" command returns the modules implemented, normally base, receive and transmit.
* The "receive" command reads an IR signal using the used, demodulating IR sensor.
* The "send" commands transmits a supplied raw signal the requested number of times.
*
* Only the first character of the command is evaluated in this implementation.
*
* The "receive" command returns the received IR sequence as a sequence
* of durations, including a (dummy) trailing silence. On-periods
* ("marks", "flashes") are prefixed by "+", while off-periods ("spaces",
* "gaps") are prefixed by "-". The present version never times out.
*
* The \c send command takes the following parameters:
*
* send noSends frequencyHz introLength repeatLength endingLength durations...
* where
*
* * frequencyHz denotes the modulation frequency in Hz
* (\e not khz, as is normally used in IRremote)
* * introLength denotes the length of the intro sequence, must be even,
* * repeatLength denotes the length of the repeat sequence, must be even,
* * endingLength denotes the length of the ending sequence (normally 0), must be even.
* * duration... denotes the microsecond durations to send,
* starting with the first on-period, ending with a (possibly dummy) trailing silence
*
* Semantics: first the intro sequence will be sent once (i.e., the first
* repeatLength durations) (if non-empty). Then the repeat sequence will
* be sent (noSends-1) times, unless the intro sequence was empty, in
* which case it will be send noSends times. Finally, the ending
* sequence will be send once (if non-empty).
*
* Weaknesses of the IRremote implementation:
* * Reception never times out if no IR is seen.
* * The IRrecv class does its own decoding which is irrelevant for us.
* * The timeout at the end on a signal reception is not configurable.
* For example, a NEC1 type signal will cut after the intro sequence,
* and the repeats will be considered independent signals.
* In IrSqrutinizer, recognition of repeating signals will therefore not work.
* The size of the data is platform dependent ("unsigned int", which is 16 bit on AVR boards, 32 bits on 32 bit boards).
*
*/
#include <Arduino.h>
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
// Change the following two entries if desired
/**
* Baud rate for the serial/USB connection.
* (115200 is the default for IrScrutinizer and Lirc.)
*/
#define BAUDRATE 115200
#define NO_DECODER
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include "IRremote.hpp"
#include <limits.h>
/**
* Define to support reception of IR.
*/
#define RECEIVE
/**
* Define to support transmission of IR signals.
*/
#define TRANSMIT
// (The sending pin is in general not configurable, see the documentation of IRremote.)
/**
* Character that ends the command lines. Do not change unless you known what
* you are doing. IrScrutinizer and Lirc expects \r.
*/
#define EOLCHAR '\r'
////// End of user configurable variables ////////////////////
/**
* The modules supported, as given by the "modules" command.
*/
#if defined(TRANSMIT)
#if defined(RECEIVE)
#define modulesSupported "base transmit receive"
#else // ! RECEIVE
#define modulesSupported "base transmit"
#endif
#else // !TRANSMIT
#if defined(RECEIVE)
#define modulesSupported "base receive"
#else // ! RECETVE
#error At lease one of TRANSMIT and RECEIVE must be defined
#endif
#endif
/**
* Name of program, as reported by the "version" command.
*/
#define PROGNAME "MicroGirs"
/**
* Version of program, as reported by the "version" command.
*/
#define VERSION "2020-07-05"
#define okString "OK"
#define errorString "ERROR"
#define timeoutString "."
// For compatibility with IRremote, we deliberately use
// the platform dependent types.
// (Although it is a questionable idea ;-) )
/**
* Type used for modulation frequency in Hz (\e not kHz).
*/
typedef unsigned frequency_t; // max 65535, unless 32-bit
/**
* Type used for durations in micro seconds.
*/
typedef uint16_t microseconds_t; // max 65535
static const microseconds_t DUMMYENDING = 40000U;
static const frequency_t FREQUENCY_T_MAX = UINT16_MAX;
static const frequency_t MICROSECONDS_T_MAX = UINT16_MAX;
/**
* Our own tokenizer class. Breaks the command line into tokens.
* Usage outside of this package is discouraged.
*/
class Tokenizer {
private:
static const int invalidIndex = -1;
int index; // signed since invalidIndex is possible
const String &payload;
void trim();
public:
Tokenizer(const String &str);
String getToken();
String getRest();
String getLine();
long getInt();
microseconds_t getMicroseconds();
frequency_t getFrequency();
static const int invalid = INT_MAX;
};
Tokenizer::Tokenizer(const String &str) :
index(0), payload(str) {
}
String Tokenizer::getRest() {
String result = index == invalidIndex ? String("") : payload.substring(index);
index = invalidIndex;
return result;
}
String Tokenizer::getLine() {
if (index == invalidIndex)
return String("");
int i = payload.indexOf('\n', index);
String s = (i > 0) ? payload.substring(index, i) : payload.substring(index);
index = (i > 0) ? i + 1 : invalidIndex;
return s;
}
String Tokenizer::getToken() {
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++;
return s;
}
long Tokenizer::getInt() {
String token = getToken();
return token == "" ? (long) invalid : token.toInt();
}
microseconds_t Tokenizer::getMicroseconds() {
long t = getToken().toInt();
return (microseconds_t) ((t < MICROSECONDS_T_MAX) ? t : MICROSECONDS_T_MAX);
}
frequency_t Tokenizer::getFrequency() {
long t = getToken().toInt();
return (frequency_t) ((t < FREQUENCY_T_MAX) ? t : FREQUENCY_T_MAX);
}
///////////////// end Tokenizer /////////////////////////////////
#if defined(TRANSMIT)
static inline unsigned hz2khz(frequency_t hz) {
return (hz + 500) / 1000;
}
/**
* Transmits the IR signal given as argument.
*
* The intro sequence (possibly empty) is first sent. Then the repeat signal
* (also possibly empty) is sent, "times" times, except for the case of
* the intro signal being empty, in which case it is sent "times" times.
* Finally the ending sequence (possibly empty) is sent.
*
* @param intro Sequence to be sent exactly once at the start.
* @param lengthIntro Number of durations in intro sequence, must be even.
* @param repeat Sequence top possibly be sent multiple times
* @param lengthRepeat Number of durations in repeat sequence.
* @param ending Sequence to be sent at the end, possibly empty
* @param lengthEnding Number of durations in ending sequence
* @param frequency Modulation frequency, in Hz (not kHz as normally in IRremote)
* @param times Number of times to send the signal, in the sense above.
*/
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));
}
#endif // TRANSMIT
#if defined(RECEIVE)
static void dump(Stream &stream) {
unsigned int count = IrReceiver.decodedIRData.rawDataPtr->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(" ");
}
stream.print('-');
stream.println(DUMMYENDING);
}
/**
* Reads a command from the stream given as argument.
* @param stream Stream to read from, typically Serial.
*/
static void receive(Stream &stream) {
IrReceiver.start();
while (!IrReceiver.decode()) {
}
IrReceiver.stop();
dump(stream);
}
#endif // RECEIVE
/**
* Initialization.
*/
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
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
#if defined(RECEIVE)
// 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.print(F("at pin "));
#endif
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
}
static String readCommand(Stream &stream) {
while (stream.available() == 0) {
}
String line = stream.readStringUntil(EOLCHAR);
line.trim();
return line;
}
static void processCommand(const String &line, Stream &stream) {
Tokenizer tokenizer(line);
String cmd = tokenizer.getToken();
// Decode the command in cmd
if (cmd.length() == 0) {
// empty command, do nothing
stream.println(F(okString));
return;
}
switch (cmd[0]) {
case 'm':
stream.println(F(modulesSupported));
break;
#if defined(RECEIVE)
case 'r': // receive
//case 'a':
//case 'c':
receive(stream);
break;
#endif // RECEIVE
#if defined(TRANSMIT)
case 's': // send
{
// TODO: handle unparsable data gracefully
unsigned noSends = (unsigned) tokenizer.getInt();
frequency_t frequency = tokenizer.getFrequency();
unsigned introLength = (unsigned) tokenizer.getInt();
unsigned repeatLength = (unsigned) tokenizer.getInt();
unsigned endingLength = (unsigned) tokenizer.getInt();
microseconds_t intro[introLength];
microseconds_t repeat[repeatLength];
microseconds_t ending[endingLength];
for (unsigned i = 0; i < introLength; i++)
intro[i] = tokenizer.getMicroseconds();
for (unsigned i = 0; i < repeatLength; i++)
repeat[i] = tokenizer.getMicroseconds();
for (unsigned i = 0; i < endingLength; i++)
ending[i] = tokenizer.getMicroseconds();
sendRaw(intro, introLength, repeat, repeatLength, ending, endingLength, frequency, noSends);
stream.println(F(okString));
}
break;
#endif // TRANSMIT
case 'v': // version
stream.println(F(PROGNAME " " VERSION));
break;
default:
stream.println(F(errorString));
}
}
/**
* Reads a command from the serial line and executes it-
*/
void loop() {
String line = readCommand(Serial);
processCommand(line, Serial);
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,148 @@
/*
* MinimalReceiver.cpp
*
* 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, bool isRepetition)
* is called in Interrupt context but with interrupts being enabled to enable use of delay() etc.
* !!!!!!!!!!!!!!!!!!!!!!
* Functions called in interrupt context should be running as short as possible,
* so if you require longer action, save the data (address + command) and handle it in the main loop.
* !!!!!!!!!!!!!!!!!!!!!
*
*
* Copyright (C) 2020-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* MinimalReceiver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#include <Arduino.h>
/*
* Set 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(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
//#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.
*/
#include "TinyIRReceiver.hpp"
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
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!
#endif
// Just to know which program is running on my Arduino
#if defined(ESP8266)
Serial.println();
#endif
Serial.println(F("START " __FILE__ " from " __DATE__));
initPCIInterruptForTinyReceiver();
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN)));
}
void loop()
{
if (sCallbackData.justWritten)
{
sCallbackData.justWritten = false;
Serial.print(F("Address=0x"));
Serial.print(sCallbackData.Address, HEX);
Serial.print(F(" Command=0x"));
Serial.print(sCallbackData.Command, HEX);
if (sCallbackData.isRepeat)
{
Serial.print(F(" Repeat"));
}
Serial.println();
}
/*
* Put your code here
*/
}
/*
* This is the function is called if a complete command was received
* It runs in an ISR context with interrupts enabled, so functions like delay() etc. are working here
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat)
#else
void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat)
#endif
{
#if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
// Copy data for main loop, this is the recommended way for handling a callback :-)
sCallbackData.Address = aAddress;
sCallbackData.Command = aCommand;
sCallbackData.isRepeat = isRepeat;
sCallbackData.justWritten = true;
#else
/*
* This is not allowed in ISR context for any kind of RTOS
* 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
Serial.print(F("A=0x"));
Serial.print(aAddress, HEX);
Serial.print(F(" C=0x"));
Serial.print(aCommand, HEX);
Serial.print(F(" R="));
Serial.print(isRepeat);
Serial.println();
#endif
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,198 @@
/*
* ReceiveAndSend.cpp
*
* Record and play back last received IR signal at button press.
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
*
* An example for simultaneous receiving and sending is in the UnitTest example.
*
* An IR detector/demodulator must be connected to the input IR_RECEIVE_PIN.
*
* 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.
*
*
* Initially coded 2009 Ken Shirriff http://www.righto.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2021 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
* 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 <Arduino.h>
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 900 bytes program memory
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
int SEND_BUTTON_PIN = APPLICATION_PIN;
int STATUS_PIN = LED_BUILTIN;
int DELAY_BETWEEN_REPEAT = 50;
int DEFAULT_NUMBER_OF_REPEATS_TO_SEND = 3;
// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif
// Storage for the recorded code
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
} sStoredIRData;
int lastButtonState;
void storeCode(IRData *aIRReceivedData);
void sendCode(storedIRDataStruct *aIRDataToSend);
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!
#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);
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
pinMode(STATUS_PIN, OUTPUT);
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_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);
}
void loop() {
// If button pressed, send the code.
int buttonState = digitalRead(SEND_BUTTON_PIN); // Button pin is active LOW
/*
* Check for button just released in order to activate receiving
*/
if (lastButtonState == LOW && buttonState == HIGH) {
// Re-enable receiver
Serial.println(F("Button released"));
IrReceiver.start();
}
/*
* Check for static button state
*/
if (buttonState == LOW) {
IrReceiver.stop();
/*
* Button pressed send stored data or repeat
*/
Serial.println(F("Button pressed, now sending"));
digitalWrite(STATUS_PIN, HIGH);
if (lastButtonState == buttonState) {
sStoredIRData.receivedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
}
sendCode(&sStoredIRData);
digitalWrite(STATUS_PIN, LOW);
delay(DELAY_BETWEEN_REPEAT); // Wait a bit between retransmissions
/*
* Button is not pressed, check for incoming data
*/
} else if (IrReceiver.available()) {
storeCode(IrReceiver.read());
IrReceiver.resume(); // resume receiver
}
lastButtonState = buttonState;
}
// Stores the code for later playback in sStoredIRData
// Most of this code is just logging
void storeCode(IRData *aIRReceivedData) {
if (aIRReceivedData->flags & IRDATA_FLAGS_IS_REPEAT) {
Serial.println(F("Ignore repeat"));
return;
}
if (aIRReceivedData->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
Serial.println(F("Ignore autorepeat"));
return;
}
if (aIRReceivedData->flags & IRDATA_FLAGS_PARITY_FAILED) {
Serial.println(F("Ignore parity error"));
return;
}
/*
* Copy decoded data
*/
sStoredIRData.receivedIRData = *aIRReceivedData;
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;
/*
* Store the current raw data in a dedicated array for later usage
*/
IrReceiver.compensateAndStoreIRResultInArray(sStoredIRData.rawCode);
} else {
IrReceiver.printIRResultShort(&Serial);
sStoredIRData.receivedIRData.flags = 0; // clear flags -esp. repeat- for later sending
Serial.println();
}
}
void sendCode(storedIRDataStruct *aIRDataToSend) {
if (aIRDataToSend->receivedIRData.protocol == UNKNOWN /* i.e. raw */) {
// Assume 38 KHz
IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38);
Serial.print(F("Sent raw "));
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, DEFAULT_NUMBER_OF_REPEATS_TO_SEND);
Serial.print(F("Sent: "));
printIRResultShort(&Serial, &aIRDataToSend->receivedIRData, false);
}
}

View File

@@ -0,0 +1,151 @@
START ../src/ReceiveDemo.cpp from Mar 8 2021
Using library version 3.1.0
Enabling IRin...
Ready to receive IR signals at pin 2
20 us are subtracted from all marks and added to all spaces for decoding
Protocol=NEC Address=0x2 Command=0x34 Raw-Data=0xCB34FD02 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Parity fail Raw-Data=0xC0340102 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=APPLE Address=0x2 Command=0x34 Raw-Data=0x23487EE 32 bits LSB first
Protocol=PANASONIC Address=0x102 Command=0x34 Raw-Data=0x4341020 48 bits LSB first
Protocol=KASEIKYO Address=0x102 Command=0x34 Extra=0x4711 Raw-Data=0x7341023 48 bits LSB first
Protocol=DENON Address=0x2 Command=0x34 Raw-Data=0x8D0 15 bits MSB first
Protocol=DENON Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2F 15 bits MSB first
Protocol=SHARP Address=0x2 Command=0x34 Raw-Data=0x8D2 15 bits MSB first
Protocol=SHARP Address=0x2 Command=0x34 Auto-Repeat gap=44600us Raw-Data=0xB2D 15 bits MSB first
Protocol=SONY Address=0x2 Command=0x34 Raw-Data=0x134 12 bits LSB first
Protocol=SONY Address=0x2 Command=0x34 Raw-Data=0x134 15 bits LSB first
Protocol=SONY Address=0x0 Command=0x0 Raw-Data=0x0 0 bits LSB first
Protocol=SONY Address=0x102 Command=0x34 Raw-Data=0x8134 20 bits LSB first
Protocol=RC5 Address=0x2 Command=0x34 Toggle=1 Raw-Data=0x38B4 13 bits MSB first
Protocol=RC5 Address=0x2 Command=0x74 Raw-Data=0x20B4 13 bits MSB first
Protocol=RC6 Address=0x2 Command=0x34 Raw-Data=0x234 16 bits MSB first
Protocol=SAMSUNG Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=JVC Address=0x2 Command=0x34 Raw-Data=0x3402 16 bits LSB first
Protocol=LG Address=0x2 Command=0x34 Raw-Data=0x200347 28 bits MSB first
Protocol=BOSEWAVE Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Protocol=LEGO_PF Address=0x3 Command=0x14 Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x14 Auto-Repeat gap=216800us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Overflow detected
Protocol=NEC Address=0x3 Command=0x45 Raw-Data=0xBA45FC03 32 bits LSB first
Protocol=NEC Address=0x3 Command=0x45 Repeat gap=47550us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Protocol=NEC Address=0x203 Command=0x45 Repeat gap=47550us
Protocol=APPLE Address=0x3 Command=0x45 Raw-Data=0x34587EE 32 bits LSB first
Protocol=APPLE Address=0x3 Command=0x45 Repeat gap=47550us
Protocol=PANASONIC Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Protocol=PANASONIC Address=0x203 Command=0x45 Repeat gap=73250us Raw-Data=0x55452030 48 bits LSB first
Protocol=KASEIKYO Address=0x203 Command=0x45 Extra=0x4711 Raw-Data=0x56452033 48 bits LSB first
Protocol=KASEIKYO Address=0x203 Command=0x45 Extra=0x4711 Repeat gap=73250us Raw-Data=0x56452033 48 bits LSB first
Protocol=DENON Address=0x3 Command=0x45 Raw-Data=0xD14 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEEB 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Repeat gap=44550us Raw-Data=0xD14 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEEB 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Raw-Data=0xD16 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEE9 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Repeat gap=44550us Raw-Data=0xD16 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEE9 15 bits MSB first
Protocol=SONY Address=0x3 Command=0x45 Raw-Data=0x1C5 12 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Repeat gap=24350us Raw-Data=0x1C5 12 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Raw-Data=0x1C5 15 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Repeat gap=24350us Raw-Data=0x1C5 15 bits LSB first
Protocol=SONY Address=0x203 Command=0x45 Raw-Data=0x101C5 20 bits LSB first
Protocol=SONY Address=0x203 Command=0x45 Repeat gap=24300us Raw-Data=0x101C5 20 bits LSB first
Protocol=RC5 Address=0x3 Command=0x5 Raw-Data=0x30C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x5 Repeat gap=99000us Raw-Data=0x30C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x45 Toggle=1 Raw-Data=0x28C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x45 Toggle=1 Repeat gap=98950us Raw-Data=0x28C5 13 bits MSB first
Protocol=RC6 Address=0x3 Command=0x45 Raw-Data=0x345 16 bits MSB first
Protocol=RC6 Address=0x3 Command=0x45 Repeat gap=106400us Raw-Data=0x345 16 bits MSB first
Protocol=SAMSUNG Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Protocol=SAMSUNG Address=0x203 Command=0x45 Repeat gap=54500us
Protocol=JVC Address=0x3 Command=0x45 Raw-Data=0x4503 16 bits LSB first
Protocol=JVC Address=0x3 Command=0x45 Repeat gap=22750us
Protocol=LG Address=0x3 Command=0x45 Raw-Data=0x300459 28 bits MSB first
Protocol=LG Address=0x3 Command=0x45 Repeat gap=51500us
Protocol=BOSEWAVE Address=0x0 Command=0x45 Raw-Data=0xBA45 16 bits LSB first
Protocol=BOSEWAVE Address=0x0 Command=0x45 Repeat gap=51450us Raw-Data=0xBA45 16 bits LSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Overflow detected

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,208 @@
/*
* ReceiveDemo.cpp
*
* Demonstrates receiving IR codes with the IRremote library and the use of the Arduino tone() function with this library.
* If debug button is pressed (pin connected to ground) a long output is generated.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
/*
* Specify which protocol(s) should be used for decoding.
* If no protocol is defined, all protocols are active.
* This must be done before the #include <IRremote.hpp>
*/
//#define DECODE_LG
//#define DECODE_NEC
// etc. see IRremote.hpp
//
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
#if FLASHEND <= 0x1FFF // For 8k flash or less, like ATtiny85. Exclude exotic protocols.
#define EXCLUDE_EXOTIC_PROTOCOLS
# if !defined(DIGISTUMPCORE) // ATTinyCore is bigger than Digispark core
#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
# endif
#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 _IR_MEASURE_TIMING
// 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.
//#define MARK_EXCESS_MICROS 20 // 20 is recommended for the cheap VS1838 modules
//#define RECORD_GAP_MICROS 12000 // 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.
#include <IRremote.hpp>
#if defined(APPLICATION_PIN)
#define DEBUG_BUTTON_PIN APPLICATION_PIN // if low, print timing for each received data set
#else
#define DEBUG_BUTTON_PIN 6
#endif
// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif
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);
#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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
// In case the interrupt driver crashes on setup, give a clue
// to the user what's going on.
Serial.println(F("Enabling IRin..."));
// 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)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
Serial.print(F("Debug button pin is "));
Serial.println(DEBUG_BUTTON_PIN);
// 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"));
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
#endif
}
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()) {
Serial.println();
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
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#modifying-compile-options-with-sloeber-ide
# if !defined(ESP8266) && !defined(NRF5)
/*
* do double beep
*/
# 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 {
// Print a short summary of received data
IrReceiver.printIRResultShort(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
}
// tone on esp8266 works once, then it disables the successful IrReceiver.start() / timerConfigForReceive().
# if !defined(ESP8266) && !defined(NRF5)
if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
/*
* If a valid protocol was received, play tone, wait and restore IR timer.
* Otherwise do not play a tone to get exact gap time between transmissions.
* 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); // to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
# endif
}
# endif
#else
// Print a minimal summary of received data
IrReceiver.printIRResultMinimal(&Serial);
#endif // FLASHEND
/*
* !!!Important!!! Enable receiving of the next value,
* since receiving has stopped after the end of the current received data packet.
*/
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.decode())
/*
* Your code here
* For all users of the FastLed library, use this code for strip.show() to improve receiving performance (which is still not 100%):
* if (IrReceiver.isIdle()) {
* strip.show();
* }
*/
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,129 @@
/*
* ReceiveDump.cpp
*
* Dumps the received signal in different flavors.
* Since the printing takes so much time, repeat signals may be skipped or interpreted as UNKNOWN.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
/*
* 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 // recommended for the cheap VS1838 modules
//#define RECORD_GAP_MICROS 12000 // 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.
#include <IRremote.hpp>
//+=============================================================================
// Configure the Arduino
//
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!
#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 IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
// 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"));
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
}
//+=============================================================================
// The repeating section of the code
//
void loop() {
if (IrReceiver.decode()) { // Grab an IR code
// Check if the buffer overflowed
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#modifying-compile-options-with-sloeber-ide
} else {
Serial.println(); // 2 blank lines between entries
Serial.println();
IrReceiver.printIRResultShort(&Serial);
Serial.println();
Serial.println(F("Raw result in internal ticks (50 us) - with leading gap"));
IrReceiver.printIRResultRawFormatted(&Serial, false); // Output the results in RAW format
Serial.println(F("Raw result in microseconds - with leading gap"));
IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
Serial.println(); // blank line between entries
Serial.print(F("Result as internal 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.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
IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables
IrReceiver.compensateAndPrintIRResultAsPronto(&Serial);
/*
* 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.
*/
// Serial.println(); // blank line between entries
// String ProntoHEX = F("Pronto HEX contains: "); // Assign string to ProtoHex string object
// if (int size = IrReceiver.compensateAndStorePronto(&ProntoHEX)) { // Dump the content of the IReceiver Pronto HEX to the String object
// // Append compensateAndStorePronto() size information to the String object (requires 50 bytes heap)
// ProntoHEX += F("\r\nProntoHEX is "); // Add codes size information to the String object
// ProntoHEX += size;
// ProntoHEX += F(" characters long and contains "); // Add codes count information to the String object
// ProntoHEX += size / 5;
// ProntoHEX += F(" codes");
// Serial.println(ProntoHEX.c_str()); // Print to the serial console the whole String object
// Serial.println(); // blank line between entries
// }
}
IrReceiver.resume(); // Prepare for the next value
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,210 @@
/*
* ReceiveOneAndSendMultiple.cpp
*
* Serves as a IR remote macro expander
* Receives Samsung32 protocol and on receiving a specified input frame,
* it sends multiple Samsung32 frames with appropriate delays in between.
* This serves as a Netflix-key emulation for my old Samsung H5273 TV.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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.
*
************************************************************************************
*/
// Digispark ATMEL ATTINY85
// Piezo speaker must have a 270 Ohm resistor in series for USB programming and running at the Samsung TV.
// IR LED has a 270 Ohm resistor in series.
// +-\/-+
// !RESET (5) PB5 1| |8 Vcc
// USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output
// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED
// GND 4| |5 PB0 (0) IR Input
// +----+
#include <Arduino.h>
// 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()
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
void sendSamsungSmartHubMacro(bool aDoSelect);
void IRSendWithDelay(uint8_t aCommand, uint16_t aDelayMillis);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_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
tone(TONE_PIN, 2200, 400);
digitalWrite(LED_BUILTIN, HIGH);
delay(400);
digitalWrite(LED_BUILTIN, LOW);
// 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);
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
}
void loop() {
/*
* Check if new data available and get them
*/
if (IrReceiver.decode()) {
// Print a short summary of received data
IrReceiver.printIRResultShort(&Serial);
Serial.println();
/*
* Here data is available -> evaluate IR command
*/
switch (IrReceiver.decodedIRData.command) {
case 0x47: // The play key on the bottom of my Samsung remote
Serial.println(F("Play key detected, open Netflix"));
sendSamsungSmartHubMacro(true);
break;
case 0x4A: // The pause key on the bottom of my Samsung remote
Serial.println(F("Pause key detected, open SmartHub"));
sendSamsungSmartHubMacro(false);
break;
default:
break;
}
/*
* !!!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
}
}
void IRSendWithDelay(uint8_t aCommand, uint16_t aDelayMillis) {
IrSender.sendSamsung(ADDRESS_OF_SAMSUNG_REMOTE, aCommand, 1); // send with one repeat
Serial.print(F("Send Samsung command 0x"));
Serial.println(aCommand);
delay(aDelayMillis);
}
bool sMacroWasCalledBefore = false;
#define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error
#define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed
/*
* This macro calls the last SmartHub application you selected manually
*
* @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu
*
*/
void sendSamsungSmartHubMacro(bool aDoSelect) {
uint32_t tWaitTimeAfterBoot;
if (aDoSelect) {
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS;
} else {
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS;
}
# if !defined(ESP32)
IrReceiver.stop(); // ESP32 uses another timer for tone()
# endif
if (millis() < tWaitTimeAfterBoot) {
// division by 1000 and printing requires much (8%) program memory
Serial.print(F("It is "));
Serial.print(millis() / 1000);
Serial.print(F(" seconds after boot, Samsung H5273 TV requires "));
Serial.print(tWaitTimeAfterBoot / 1000);
Serial.println(F(" seconds after boot to be ready for the command"));
tone(TONE_PIN, 2200, 100);
delay(200);
tone(TONE_PIN, 2200, 100);
delay(100);
if (millis() < tWaitTimeAfterBoot) {
Serial.print(F("Now do a blocking wait for "));
Serial.print(tWaitTimeAfterBoot - millis());
Serial.println(F(" milliseconds"));
delay(tWaitTimeAfterBoot - millis());
}
}
// Do beep feedback for special key to be received
tone(TONE_PIN, 2200, 200);
delay(200);
# if !defined(ESP32)
IrReceiver.start(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement.
# endif
Serial.println(F("Wait for \"not supported\" to disappear"));
delay(2000);
Serial.println(F("Start sending of Samsung IR macro"));
IRSendWithDelay(0x1A, 2000); // Menu and wait for the Menu to pop up
Serial.println(F("Wait for the menu to pop up"));
if (!sMacroWasCalledBefore) {
delay(2000); // wait additional time for the Menu load
}
for (uint_fast8_t i = 0; i < 4; ++i) {
IRSendWithDelay(0x61, 250); // Down arrow. For my Samsung, the high byte of the command is the inverse of the low byte
}
IRSendWithDelay(0x62, 400); // Right arrow
for (uint_fast8_t i = 0; i < 2; ++i) {
IRSendWithDelay(0x61, 250); // Down arrow
}
delay(250);
IRSendWithDelay(0x68, 1); // Enter for SmartHub
if (aDoSelect) {
Serial.println(F("Wait for SmartHub to show up, before entering current application"));
delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears
IRSendWithDelay(0x68, 1); // Enter for last application (e.g. Netflix or Amazon)
}
sMacroWasCalledBefore = true;
Serial.println(F("Done"));
}

View File

@@ -0,0 +1,262 @@
/*
* ReceiverTimingAnalysis.cpp
*
* This program enables the pin change interrupt at pin 3 and waits for NEC (or other Pulse-Distance-Coding) IR Signal.
* It measures the pulse and pause times of the incoming signal and computes some statistics for it.
*
* Observed values:
* Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level.
* VS1838 Mark Excess -50 to +50 us
* TSOP31238 Mark Excess 0 to +50
*
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#include <Arduino.h>
#define IR_INPUT_PIN 2
//#define IR_INPUT_PIN 3
/*
* Helper macro for getting a macro definition as string
*/
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
void measureTimingISR(void);
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!
#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)
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)
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);
#endif
Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_INPUT_PIN)));
Serial.println();
}
uint8_t ISREdgeCounter = 0;
volatile uint32_t LastMicros;
struct timingStruct
{
uint16_t minimum;
uint8_t indexOfMinimum;
uint16_t maximum;
uint8_t indexOfMaximum;
uint16_t average;
uint16_t SumForAverage;
uint8_t SampleCount;
// uint8_t LastPrintedCount;
};
struct timingStruct Mark;
struct timingStruct ShortSpace;
struct timingStruct LongSpace;
/*
* Compute minimum, maximum and average
*/
void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue)
{
if (aTimingStruct->SampleCount == 0)
{
// initialize values
aTimingStruct->minimum = UINT16_MAX;
aTimingStruct->maximum = 0;
aTimingStruct->SumForAverage = 0;
}
if (aTimingStruct->minimum > aValue)
{
aTimingStruct->minimum = aValue;
aTimingStruct->indexOfMinimum = aTimingStruct->SampleCount;
}
if (aTimingStruct->maximum < aValue)
{
aTimingStruct->maximum = aValue;
aTimingStruct->indexOfMaximum = aTimingStruct->SampleCount;
}
aTimingStruct->SampleCount++;
aTimingStruct->SumForAverage += aValue;
aTimingStruct->average = (aTimingStruct->SumForAverage + (aTimingStruct->SampleCount / 2)) / aTimingStruct->SampleCount;
}
void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption)
{
// if (aTimingStruct->LastPrintedCount != aTimingStruct->SampleCount)
// {
// aTimingStruct->LastPrintedCount = aTimingStruct->SampleCount;
Serial.print(aCaption);
Serial.print(F(": SampleCount="));
Serial.print(aTimingStruct->SampleCount);
Serial.print(F(" Minimum="));
Serial.print(aTimingStruct->minimum);
Serial.print(F(" @"));
Serial.print(aTimingStruct->indexOfMinimum);
Serial.print(F(" Maximum="));
Serial.print(aTimingStruct->maximum);
Serial.print(F(" @"));
Serial.print(aTimingStruct->indexOfMaximum);
Serial.print(F(" Delta="));
Serial.print(aTimingStruct->maximum - aTimingStruct->minimum);
Serial.print(F(" Average="));
Serial.print(aTimingStruct->average);
Serial.println();
// }
}
void loop()
{
if (Mark.SampleCount >= 32)
{
/*
* This check enables statistics for longer protocols like Kaseikyo/Panasonics
*/
#if !defined(ARDUINO_ARCH_MBED)
noInterrupts();
#endif
uint32_t tLastMicros = LastMicros;
#if !defined(ARDUINO_ARCH_MBED)
interrupts();
#endif
uint32_t tMicrosDelta = micros() - tLastMicros;
if (tMicrosDelta > 10000)
{
// NEC signal ended just now
Serial.println();
printTimingValues(&Mark, "Mark ");
printTimingValues(&ShortSpace, "ShortSpace");
printTimingValues(&LongSpace, "LongSpace ");
/*
* Print analysis of mark and short spaces
*/
Serial.println(F("Analysis :"));
Serial.print(F(" (Average of mark + short space)/2 = "));
int16_t MarkAndShortSpaceAverage = (Mark.average + ShortSpace.average) / 2;
Serial.print(MarkAndShortSpaceAverage);
Serial.print(F(" us\r\n Delta (to NEC standard 560) = "));
Serial.print(MarkAndShortSpaceAverage - 560);
Serial.print(F("us\r\n MARK_EXCESS_MICROS = (Average of mark - Average of mark and short space) = "));
Serial.print((int16_t) Mark.average - MarkAndShortSpaceAverage);
Serial.print(F("us"));
Serial.println();
Serial.println();
Mark.SampleCount = 0; // used as flag for not printing the results more than once
}
}
}
/*
* The interrupt handler.
* Just add to the appropriate timing structure.
*/
#if defined(ESP8266)
void ICACHE_RAM_ATTR measureTimingISR()
#elif defined(ESP32)
void IRAM_ATTR measureTimingISR()
#else
# if defined(EICRA) && defined(EIFR) && defined(EIMSK)
# if (IR_INPUT_PIN == 2)
ISR(INT0_vect)
# elif (IR_INPUT_PIN == 3)
ISR(INT1_vect)
# endif
# else
void measureTimingISR()
# endif
#endif
{
uint32_t tMicros = micros();
uint32_t tMicrosDelta = tMicros - LastMicros;
LastMicros = tMicros;
/*
* read level and give feedback
*/
uint8_t tInputLevel = digitalRead(IR_INPUT_PIN);
digitalWrite(LED_BUILTIN, !tInputLevel);
if (tMicrosDelta > 10000)
{
// gap > 10 ms detected, reset counter to first detected edge and initialize timing structures
ISREdgeCounter = 1;
LongSpace.SampleCount = 0;
ShortSpace.SampleCount = 0;
Mark.SampleCount = 0;
}
else
{
ISREdgeCounter++;
}
/*
* Skip header mark and space and first bit mark and space
*/
if (ISREdgeCounter > 4)
{
if (tInputLevel != LOW)
{
// Mark ended
processTmingValue(&Mark, tMicrosDelta);
// Serial.print('M');
}
else
{
// Space ended
if (tMicrosDelta > 1000)
{
// long space - logical 1
processTmingValue(&LongSpace, tMicrosDelta);
Serial.print('1');
}
else
{
// short space - logical 0
processTmingValue(&ShortSpace, tMicrosDelta);
Serial.print('0');
}
}
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,159 @@
/*
* SendAndReceive.cpp
*
* Demonstrates sending IR codes and receiving it simultaneously
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2021 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 <Arduino.h>
// select only NEC and the universal decoder for pulse distance protocols
#define DECODE_NEC // Includes Apple and Onkyo
#define DECODE_DISTANCE // in case NEC is not received correctly
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS
//#define SEND_PWM_BY_TIMER
//#define USE_NO_SEND_PWM
//#define NO_LED_FEEDBACK_CODE // saves 500 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.
#include <IRremote.hpp>
#define DELAY_AFTER_SEND 2000
#define DELAY_AFTER_LOOP 5000
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!
#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);
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
// For esp32 we use PWM generation by ledcWrite() for each pin.
# if !defined(SEND_PWM_BY_TIMER) && !defined(USE_NO_SEND_PWM) && !defined(ESP32)
/*
* Print internal software PWM generation info
*/
IrSender.enableIROut(38); // Call it with 38 kHz to initialize the values printed below
Serial.print(F("Send signal mark duration is "));
Serial.print(IrSender.periodOnTimeMicros);
Serial.print(F(" us, pulse correction is "));
Serial.print(IrSender.getPulseCorrectionNanos());
Serial.print(F(" ns, total period is "));
Serial.print(IrSender.periodTimeMicros);
Serial.println(F(" us"));
# endif
// 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"));
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
#endif
}
uint16_t sAddress = 0x0102;
uint8_t sCommand = 0x34;
uint8_t sRepeats = 1;
/*
* Send NEC IR protocol
*/
void send_ir_data() {
Serial.print(F("Sending: 0x"));
Serial.print(sAddress, HEX);
Serial.print(sCommand, HEX);
Serial.println(sRepeats, HEX);
// clip repeats at 4
if (sRepeats > 4) {
sRepeats = 4;
}
// Results for the first loop to: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
IrSender.sendNEC(sAddress, sCommand, sRepeats);
}
void receive_ir_data() {
if (IrReceiver.decode()) {
Serial.print(F("Decoded protocol: "));
Serial.print(getProtocolString(IrReceiver.decodedIRData.protocol));
Serial.print(F("Decoded raw data: "));
Serial.print(IrReceiver.decodedIRData.decodedRawData, HEX);
Serial.print(F(", decoded address: "));
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(F(", decoded command: "));
Serial.println(IrReceiver.decodedIRData.command, HEX);
IrReceiver.resume();
}
}
void loop() {
/*
* Print loop values
*/
Serial.println();
Serial.print(F("address=0x"));
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.println(sRepeats);
Serial.flush();
send_ir_data();
// wait for the receiver state machine to detect the end of a protocol
delay((RECORD_GAP_MICROS / 1000) + 5);
receive_ir_data();
// Prepare data for next loop
sAddress += 0x0101;
sCommand += 0x11;
sRepeats++;
delay(100); // Loop delay
}

View File

@@ -0,0 +1,38 @@
START SendAndReceive.cpp from Apr 19 2021
Using library version 3.1.1
Ready to receive IR signals at pin D5
Ready to send IR signals at pin D6
Send signal mark duration is 7 us, pulse correction is 600 ns, total period is 26 us
20 us are subtracted from all marks and added to all spaces for decoding
address=0x102 command=0x34 repeats=1
Sending: 0x102341
Decoded protocol: NECDecoded raw data: CB340102, decoded address: 102, decoded command: 34
address=0x203 command=0x45 repeats=2
Sending: 0x203452
Decoded protocol: NECDecoded raw data: BA450203, decoded address: 203, decoded command: 45
address=0x304 command=0x56 repeats=3
Sending: 0x304563
Decoded protocol: NECDecoded raw data: A9560304, decoded address: 304, decoded command: 56
address=0x405 command=0x67 repeats=4
Sending: 0x405674
Decoded protocol: NECDecoded raw data: 98670405, decoded address: 405, decoded command: 67
address=0x506 command=0x78 repeats=5
Sending: 0x506785
Decoded protocol: NECDecoded raw data: 87780506, decoded address: 506, decoded command: 78
address=0x607 command=0x89 repeats=5
Sending: 0x607895
Decoded protocol: NECDecoded raw data: 76890607, decoded address: 607, decoded command: 89
address=0x708 command=0x9A repeats=5
Sending: 0x7089A5
Decoded protocol: NECDecoded raw data: 659A0708, decoded address: 708, decoded command: 9A
address=0x809 command=0xAB repeats=5
Sending: 0x809AB5
Decoded protocol: NECDecoded raw data: 54AB0809, decoded address: 809, decoded command: AB

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,199 @@
/*
* SendBoseWaveDemo.cpp
*
* Prompt user for a code to send. Make sure your 940-950nm IR LED is
* connected to the default digital output. Place your Bose Wave Radio
* CD in the line of sight of your LED, and send commands!
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020 Thomas Koch - 2022 AJ converted to inverted bits
*
* 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 <Arduino.h>
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
//......................................................................
//
// Bose Wave Radio CD Remote Control
// |-------------------------------------|
// | On/Off Sleep VolUp |
// | Play/Pause Stop VolDown |
// | FM AM Aux |
// | Tune Down Tune Up Mute |
// | 1 2 3 |
// | 4 5 6 |
// |-------------------------------------|
#define BOSE_CMD_ON_OFF 0x00
#define BOSE_CMD_MUTE 0x01
#define BOSE_CMD_VOL_UP 0x02
#define BOSE_CMD_VOL_DOWN 0x03
#define BOSE_CMD_PRESET_6 0x04
#define BOSE_CMD_SLEEP 0x05
#define BOSE_CMD_FM 0x06
#define BOSE_CMD_AUX 0x07
#define BOSE_CMD_AM 0x08
#define BOSE_CMD_PLAY_PAUSE 0x09
#define BOSE_CMD_STOP 0x0A
#define BOSE_CMD_TUNE_UP 0x0B
#define BOSE_CMD_TUNE_DOWN 0x0C
#define BOSE_CMD_PRESET_1 0x0D
#define BOSE_CMD_PRESET_2 0x0E
#define BOSE_CMD_PRESET_3 0x0F
#define BOSE_CMD_PRESET_4 0x10
#define BOSE_CMD_PRESET_5 0x11
// Codes for Wave Music System
// https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/BoseWaveMusicSystem.jpg)
//#define BOSE_CMD_ON_OFF 0x4C
//#define BOSE_CMD_MUTE 0x01
//#define BOSE_CMD_VOL_UP 0x03
//#define BOSE_CMD_VOL_DOWN 0x02
//#define BOSE_CMD_SLEEP 0x54
//#define BOSE_CMD_FM_AM 0x06
//#define BOSE_CMD_CD 0x53
//#define BOSE_CMD_AUX 0x0F
//#define BOSE_CMD_TRACK_BW 0x18
//#define BOSE_CMD_TRACK_FW 0x19
//#define BOSE_CMD_PLAY_PAUSE 0x1B
//#define BOSE_CMD_STOP_EJECT 0x1A
//#define BOSE_CMD_TUNE_UP 0x58
//#define BOSE_CMD_TUNE_DOWN 0x57
//#define BOSE_CMD_PRESET_1 0x07
//#define BOSE_CMD_PRESET_2 0x08
//#define BOSE_CMD_PRESET_3 0x09
//#define BOSE_CMD_PRESET_4 0x0A
//#define BOSE_CMD_PRESET_5 0x0B
//#define BOSE_CMD_PRESET_6 0x0C
//#define BOSE_CMD_TIME_MINUS 0x9E
//#define BOSE_CMD_TIME_PLUS 0x24
//#define BOSE_CMD_PLAY_MODE 0x21
//#define BOSE_CMD_ALARM_ON_OFF 0x22
//#define BOSE_CMD_ALARM_WAKE_TO 0x70
//#define BOSE_CMD_ALARM_TIME 0x23
// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif
bool sPrintMenu;
void printMenu();
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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(IR_SEND_PIN);
sPrintMenu = true;
}
void loop() {
if (sPrintMenu) {
sPrintMenu = false;
printMenu();
}
int tSerialCommandCharacter;
if (Serial.available()) {
tSerialCommandCharacter = Serial.read();
sPrintMenu = true;
if (tSerialCommandCharacter == -1) {
Serial.print(F("available() was true, but no character read")); // should not happen
} else if (tSerialCommandCharacter == 48) { // 0
IrSender.sendBoseWave(BOSE_CMD_ON_OFF); // On/Off
} else if (tSerialCommandCharacter == 49) { // 1
IrSender.sendBoseWave(BOSE_CMD_VOL_UP); // Volume Up
} else if (tSerialCommandCharacter == 50) { // 2
IrSender.sendBoseWave(BOSE_CMD_VOL_DOWN); // Volume Down
} else if (tSerialCommandCharacter == 51) { // 3
IrSender.sendBoseWave(BOSE_CMD_TUNE_UP); // Tune Up
} else if (tSerialCommandCharacter == 52) { // 4
IrSender.sendBoseWave(BOSE_CMD_TUNE_DOWN); // Tune Down
} else if (tSerialCommandCharacter == 53) { // 5
IrSender.sendBoseWave(BOSE_CMD_AM); // AM
} else if (tSerialCommandCharacter == 54) { // 6
IrSender.sendBoseWave(BOSE_CMD_FM); // FM
} else if (tSerialCommandCharacter == 55) { // 7
IrSender.sendBoseWave(BOSE_CMD_PRESET_1); // Preset 1
} else if (tSerialCommandCharacter == 56) { // 8
IrSender.sendBoseWave(BOSE_CMD_PRESET_2); // Preset 2
} else if (tSerialCommandCharacter == 57) { // 9
IrSender.sendBoseWave(BOSE_CMD_PRESET_3); // Preset 3
} else if (tSerialCommandCharacter == 97) { // a
IrSender.sendBoseWave(BOSE_CMD_PRESET_4); // Preset 4
} else if (tSerialCommandCharacter == 98) { // b
IrSender.sendBoseWave(BOSE_CMD_PRESET_5); // Preset 5
} else if (tSerialCommandCharacter == 99) { // c
IrSender.sendBoseWave(BOSE_CMD_PRESET_6); // Preset 6
} else if (tSerialCommandCharacter == 100) { // d
IrSender.sendBoseWave(BOSE_CMD_MUTE); // Mute
} else if (tSerialCommandCharacter == 101) { // e
IrSender.sendBoseWave(BOSE_CMD_PLAY_PAUSE); // Pause
} else if (tSerialCommandCharacter == 102) { // f
IrSender.sendBoseWave(BOSE_CMD_STOP); // Stop
} else if (tSerialCommandCharacter == 103) { // g
IrSender.sendBoseWave(BOSE_CMD_AUX); // Aux
} else if (tSerialCommandCharacter == 104) { // h
IrSender.sendBoseWave(BOSE_CMD_SLEEP); // Sleep
} else {
sPrintMenu = false;
}
delay(300);
}
}
void printMenu() {
Serial.println("0: On / Off");
Serial.println("1: Volume Up");
Serial.println("2: Volume Down");
Serial.println("3: Tune Up");
Serial.println("4: Tune Down");
Serial.println("5: AM");
Serial.println("6: FM");
Serial.println("7: Preset 1");
Serial.println("8: Preset 2");
Serial.println("9: Preset 3");
Serial.println("a: Preset 4");
Serial.println("b: Preset 5");
Serial.println("c: Preset 6");
Serial.println("d: Mute");
Serial.println("e: Play/Pause");
Serial.println("f: Stop");
Serial.println("g: Aux");
Serial.println("h: Sleep");
}

View File

@@ -0,0 +1,151 @@
START ../src/ReceiveDemo.cpp from Mar 8 2021
Using library version 3.1.0
Enabling IRin...
Ready to receive IR signals at pin 2
20 us are subtracted from all marks and added to all spaces for decoding
Protocol=NEC Address=0x2 Command=0x34 Raw-Data=0xCB34FD02 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Parity fail Raw-Data=0xC0340102 32 bits LSB first
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=APPLE Address=0x2 Command=0x34 Raw-Data=0x23487EE 32 bits LSB first
Protocol=PANASONIC Address=0x102 Command=0x34 Raw-Data=0x4341020 48 bits LSB first
Protocol=KASEIKYO Address=0x102 Command=0x34 Extra=0x4711 Raw-Data=0x7341023 48 bits LSB first
Protocol=DENON Address=0x2 Command=0x34 Raw-Data=0x8D0 15 bits MSB first
Protocol=DENON Address=0x2 Command=0x34 Auto-Repeat gap=44550us Raw-Data=0xB2F 15 bits MSB first
Protocol=SHARP Address=0x2 Command=0x34 Raw-Data=0x8D2 15 bits MSB first
Protocol=SHARP Address=0x2 Command=0x34 Auto-Repeat gap=44600us Raw-Data=0xB2D 15 bits MSB first
Protocol=SONY Address=0x2 Command=0x34 Raw-Data=0x134 12 bits LSB first
Protocol=SONY Address=0x2 Command=0x34 Raw-Data=0x134 15 bits LSB first
Protocol=SONY Address=0x0 Command=0x0 Raw-Data=0x0 0 bits LSB first
Protocol=SONY Address=0x102 Command=0x34 Raw-Data=0x8134 20 bits LSB first
Protocol=RC5 Address=0x2 Command=0x34 Toggle=1 Raw-Data=0x38B4 13 bits MSB first
Protocol=RC5 Address=0x2 Command=0x74 Raw-Data=0x20B4 13 bits MSB first
Protocol=RC6 Address=0x2 Command=0x34 Raw-Data=0x234 16 bits MSB first
Protocol=SAMSUNG Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Protocol=JVC Address=0x2 Command=0x34 Raw-Data=0x3402 16 bits LSB first
Protocol=LG Address=0x2 Command=0x34 Raw-Data=0x200347 28 bits MSB first
Protocol=BOSEWAVE Address=0x0 Command=0x34 Raw-Data=0xCB34 16 bits LSB first
Protocol=LEGO_PF Address=0x3 Command=0x14 Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x14 Auto-Repeat gap=216800us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Protocol=LEGO_PF Address=0x2 Command=0x14 Auto-Repeat gap=177200us Raw-Data=0x2148 16 bits MSB first
Overflow detected
Protocol=NEC Address=0x3 Command=0x45 Raw-Data=0xBA45FC03 32 bits LSB first
Protocol=NEC Address=0x3 Command=0x45 Repeat gap=47550us
Protocol=NEC Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Protocol=NEC Address=0x203 Command=0x45 Repeat gap=47550us
Protocol=APPLE Address=0x3 Command=0x45 Raw-Data=0x34587EE 32 bits LSB first
Protocol=APPLE Address=0x3 Command=0x45 Repeat gap=47550us
Protocol=PANASONIC Address=0x203 Command=0x45 Raw-Data=0x55452030 48 bits LSB first
Protocol=PANASONIC Address=0x203 Command=0x45 Repeat gap=73250us Raw-Data=0x55452030 48 bits LSB first
Protocol=KASEIKYO Address=0x203 Command=0x45 Extra=0x4711 Raw-Data=0x56452033 48 bits LSB first
Protocol=KASEIKYO Address=0x203 Command=0x45 Extra=0x4711 Repeat gap=73250us Raw-Data=0x56452033 48 bits LSB first
Protocol=DENON Address=0x3 Command=0x45 Raw-Data=0xD14 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEEB 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Repeat gap=44550us Raw-Data=0xD14 15 bits MSB first
Protocol=DENON Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEEB 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Raw-Data=0xD16 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEE9 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Repeat gap=44550us Raw-Data=0xD16 15 bits MSB first
Protocol=SHARP Address=0x3 Command=0x45 Auto-Repeat gap=44550us Raw-Data=0xEE9 15 bits MSB first
Protocol=SONY Address=0x3 Command=0x45 Raw-Data=0x1C5 12 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Repeat gap=24350us Raw-Data=0x1C5 12 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Raw-Data=0x1C5 15 bits LSB first
Protocol=SONY Address=0x3 Command=0x45 Repeat gap=24350us Raw-Data=0x1C5 15 bits LSB first
Protocol=SONY Address=0x203 Command=0x45 Raw-Data=0x101C5 20 bits LSB first
Protocol=SONY Address=0x203 Command=0x45 Repeat gap=24300us Raw-Data=0x101C5 20 bits LSB first
Protocol=RC5 Address=0x3 Command=0x5 Raw-Data=0x30C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x5 Repeat gap=99000us Raw-Data=0x30C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x45 Toggle=1 Raw-Data=0x28C5 13 bits MSB first
Protocol=RC5 Address=0x3 Command=0x45 Toggle=1 Repeat gap=98950us Raw-Data=0x28C5 13 bits MSB first
Protocol=RC6 Address=0x3 Command=0x45 Raw-Data=0x345 16 bits MSB first
Protocol=RC6 Address=0x3 Command=0x45 Repeat gap=106400us Raw-Data=0x345 16 bits MSB first
Protocol=SAMSUNG Address=0x203 Command=0x45 Raw-Data=0xBA450203 32 bits LSB first
Protocol=SAMSUNG Address=0x203 Command=0x45 Repeat gap=54500us
Protocol=JVC Address=0x3 Command=0x45 Raw-Data=0x4503 16 bits LSB first
Protocol=JVC Address=0x3 Command=0x45 Repeat gap=22750us
Protocol=LG Address=0x3 Command=0x45 Raw-Data=0x300459 28 bits MSB first
Protocol=LG Address=0x3 Command=0x45 Repeat gap=51500us
Protocol=BOSEWAVE Address=0x0 Command=0x45 Raw-Data=0xBA45 16 bits LSB first
Protocol=BOSEWAVE Address=0x0 Command=0x45 Repeat gap=51450us Raw-Data=0xBA45 16 bits LSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Protocol=LEGO_PF Address=0x3 Command=0x15 Auto-Repeat gap=216800us Raw-Data=0x3158 16 bits MSB first
Overflow detected

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,309 @@
/*
* SendDemo.cpp
*
* Demonstrates sending IR codes in standard format with address and command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
//#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
//#define NO_LED_FEEDBACK_CODE // saves 566 bytes program memory
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#define DELAY_AFTER_SEND 2000
#define DELAY_AFTER_LOOP 5000
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!
#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
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
#if defined(IR_SEND_PIN)
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
#else
Serial.println(F("Ready to send IR signals at pin 3"));
#endif
#if !defined(SEND_PWM_BY_TIMER)
/*
* Print internal signal generation info
*/
IrSender.enableIROut(38); // Call it with 38 kHz to initialize the values printed below
Serial.print(F("Send signal mark duration is "));
Serial.print(IrSender.periodOnTimeMicros);
Serial.print(F(" us, pulse correction is "));
Serial.print(IrSender.getPulseCorrectionNanos());
Serial.print(F(" ns, total period is "));
Serial.print(IrSender.periodTimeMicros);
Serial.println(F(" us"));
#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.
*/
uint16_t sAddress = 0x0102;
uint8_t sCommand = 0x34;
uint8_t sRepeats = 0;
void loop() {
/*
* Print values
*/
Serial.println();
Serial.print(F("address=0x"));
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.println(sRepeats);
Serial.println();
Serial.println();
Serial.flush();
Serial.println(F("Send NEC with 8 bit address"));
Serial.flush();
IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats);
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);
delay(DELAY_AFTER_SEND);
if (sRepeats == 0) {
#if FLASHEND >= 0x3FFF // 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"));
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 */
"0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */
"0017 003E 0017 0015 0017 003F 0017 0015 0017 0015 0017 0015 0017 003F 0017 0015 " /* command byte */
"0019 0013 0019 003C 0017 0015 0017 003F 0017 003E 0017 003F 0017 0015 0017 003E " /* inverted command byte */
"0017 0806"), 0); //stop bit, no repeat possible, because of missing repeat pattern
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)"));
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.
delay(DELAY_AFTER_SEND);
#endif
/*
* With sendNECRaw() you can send 32 bit combined codes
*/
Serial.println(F("Send NEC / ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)"));
Serial.flush();
IrSender.sendNECRaw(0x03040102, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC with 16 bit address 0x0102 and 16 bit command 0x0304 with sendPulseDistanceWidthData()"));
// Header
IrSender.mark(9000);
IrSender.space(4500);
// LSB first + stop bit
IrSender.sendPulseDistanceWidthData(560, 1680, 560, 560, 0x03040102, 32, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
IrReceiver.restartAfterSend();
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.
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
Serial.flush();
Serial.println(F("Send NEC with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first"));
IrSender.sendNECMSB(0x40802CD3, 32, false);
delay(DELAY_AFTER_SEND);
}
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
Serial.flush();
IrSender.sendOnkyo(sAddress, sCommand << 8 | sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Apple"));
Serial.flush();
IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Panasonic"));
Serial.flush();
IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID"));
Serial.flush();
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo_Denon variant"));
Serial.flush();
IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Denon"));
Serial.flush();
IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Denon/Sharp variant"));
Serial.flush();
IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 8 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5X with 7.th MSB of command set"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC6"));
Serial.flush();
IrSender.sendRC6(sAddress, sCommand, sRepeats, true);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
/*
* Next example how to use the IrSender.write function
*/
IRData IRSendData;
// prepare data
IRSendData.address = sAddress;
IRSendData.command = sCommand;
IRSendData.flags = IRDATA_FLAGS_EMPTY;
IRSendData.protocol = SAMSUNG;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
IRSendData.protocol = JVC; // switch protocol
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
IRSendData.protocol = LG;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
/*
* LEGO 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);
delay(DELAY_AFTER_SEND);
#endif // FLASHEND
/*
* 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.
// 210 + 540 = 750 should be received as 5/10 or 4/11 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
}
delay(DELAY_AFTER_SEND);
/*
* Increment values
* Also increment address just for demonstration, which normally makes no sense
*/
sAddress += 0x0101;
sCommand += 0x11;
sRepeats++;
// clip repeats at 4
if (sRepeats > 4) {
sRepeats = 4;
}
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,93 @@
=== 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<br/>
°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

View File

@@ -0,0 +1,155 @@
/*
* SendLGAirConditionerDemo.cpp
*
* Sending LG air conditioner IR codes controlled by Serial input
* Based on he old IRremote source from https://github.com/chaeplin
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
/*
* LG2 has different header timing and a shorter bit time
* Known LG remote controls, which uses LG2 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
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#endif
#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 "ac_LG.hpp"
// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif
#define SIZE_OF_RECEIVE_BUFFER 10
char sRequestString[SIZE_OF_RECEIVE_BUFFER];
Aircondition_LG MyLG_Aircondition;
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!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
/*
* The IR library setup. That's all!
*/
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(IR_SEND_PIN);
Serial.println();
MyLG_Aircondition.setType(LG_IS_WALL_TYPE);
MyLG_Aircondition.printMenu(&Serial);
delay(1000);
// test
// MyLG_Aircondition.sendCommandAndParameter('j', 1);
// delay(5000);
// MyLG_Aircondition.sendCommandAndParameter('f', 3);
// delay(5000);
}
void loop() {
static uint8_t sShowmenuConter = 0;
if (Serial.available()) {
/*
* Get parameters from serial
*/
uint8_t tNumberOfBytesReceived = Serial.readBytesUntil('\n', sRequestString, SIZE_OF_RECEIVE_BUFFER - 1);
// handle CR LF
if (sRequestString[tNumberOfBytesReceived - 1] == '\r') {
tNumberOfBytesReceived--;
}
sRequestString[tNumberOfBytesReceived] = '\0'; // terminate as string
char tCommand = sRequestString[0];
/*
* Handle parameter numbers which can be greater 9
*/
int tParameter = 0;
if (tNumberOfBytesReceived >= 2) {
tParameter = sRequestString[1] - '0';
if (tCommand == LG_COMMAND_TEMPERATURE || tCommand == LG_COMMAND_SWING || tCommand == LG_COMMAND_SLEEP
|| tCommand == LG_COMMAND_TIMER_ON || tCommand == LG_COMMAND_TIMER_OFF) {
tParameter = atoi(&sRequestString[1]);
}
}
/*
* Print command to send
*/
Serial.println();
Serial.print(F("Command="));
Serial.print(tCommand);
if (tParameter != 0) {
Serial.print(F(" Parameter="));
Serial.print(tParameter);
}
Serial.println();
if (!MyLG_Aircondition.sendCommandAndParameter(tCommand, tParameter)) {
Serial.print(F("Error: unknown command or invalid parameter in \""));
Serial.print(sRequestString);
Serial.println('\"');
}
if (sShowmenuConter == 0) {
MyLG_Aircondition.printMenu(&Serial);
sShowmenuConter = NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU;
} else {
sShowmenuConter--;
}
}
delay(100);
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,103 @@
/*
* SendProntoDemo.cpp
*
* Example for sending pronto codes with the IRremote library.
* The code used here, sends NEC protocol data.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#define NUMBER_OF_REPEATS 3U
// The first number, here 0000, denotes the type of the signal. 0000 denotes a raw IR signal with modulation.
// The second number, here 006C, denotes a frequency code. 006C corresponds to 1000000/(0x006c * 0.241246) = 38381 Hertz.
// The third and the forth number denote the number of pairs (= half the number of durations) in the start- and the repeat sequence respectively.
const char yamahaVolDown[] PROGMEM
= "0000 006C 0022 0002 015B 00AD " /* Pronto header + start bit */
"0016 0016 0016 0041 0016 0016 0016 0041 0016 0041 0016 0041 0016 0041 0016 0016 " /* Lower address byte */
"0016 0041 0016 0016 0016 0041 0016 0016 0016 0016 0016 0016 0016 0016 0016 0041 " /* Upper address byte (inverted at 8 bit mode) */
"0016 0041 0016 0041 0016 0016 0016 0041 0016 0041 0016 0016 0016 0016 0016 0016 " /* command byte */
"0016 0016 0016 0016 0016 0041 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 05F7 " /* inverted command byte + stop bit */
"015B 0057 0016 0E6C"; /* NEC repeat pattern*/
IRsend irsend;
void setup() {
Serial.begin(115200);
while (!Serial)
;
// 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
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(IR_SEND_PIN);
}
void loop() {
#if defined(__AVR__)
Serial.println(F("Sending NEC from PROGMEM: address 0x85, data 0x1B"));
irsend.sendPronto_P(yamahaVolDown, NUMBER_OF_REPEATS);
#else
Serial.println(F("Sending from normal memory"));
irsend.sendPronto(yamahaVolDown, NUMBER_OF_REPEATS);
#endif
delay(2000);
Serial.println(F("Sending the NEC from PROGMEM using the F()-form: address 0x5, data 0x1A"));
irsend.sendPronto(F("0000 006C 0022 0002 015B 00AD " /* Pronto header + start bit */
"0016 0016 0016 0041 0016 0016 0016 0041 0016 0041 0016 0041 0016 0041 0016 0041 " /* Lower address byte */
"0016 0041 0016 0016 0016 0041 0016 0016 0016 0016 0016 0016 0016 0016 0016 0016 " /* Upper address byte (inverted at 8 bit mode) */
"0016 0016 0016 0041 0016 0016 0016 0041 0016 0041 0016 0016 0016 0016 0016 0016 " /* command byte */
"0016 0041 0016 0016 0016 0041 0016 0016 0016 0016 0016 0041 0016 0041 0016 0041 0016 05F7 " /* inverted command byte + stop bit */
"015B 0057 0016 0E6C"), /* NEC repeat pattern*/
NUMBER_OF_REPEATS);
delay(2000);
// send Nec code acquired by IRreceiveDump.cpp
Serial.println(F("Sending NEC from RAM: address 0xFF00, data 0x15"));
// 006D -> 38029 Hz
irsend.sendPronto("0000 006D 0022 0000 015C 00AB " /* Pronto header + start bit */
"0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 " /* Lower address byte */
"0017 003F 0017 003E 0017 003F 0017 003E 0017 003F 0015 003F 0017 003F 0015 003F " /* Upper address byte (inverted at 8 bit mode) */
"0017 003E 0017 0015 0017 003F 0017 0015 0017 003E 0017 0015 0017 0017 0015 0017 " /* command byte */
"0017 0015 0017 003E 0017 0015 0017 003F 0015 0017 0017 003E 0017 003F 0015 003F 0017 0806" /* inverted command byte + stop bit */
, 0); // No repeat possible, because of missing repeat pattern
delay(5000);
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,120 @@
/*
* SendRawDemo.cpp - demonstrates sending IR codes with sendRaw
*
* 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
*
* If it is a supported protocol, it is more efficient to use the protocol send function
* (here sendNEC) to send the signal.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
// On the Zero and others we switch explicitly to SerialUSB
#if defined(ARDUINO_ARCH_SAMD)
#define Serial SerialUSB
#endif
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_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
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
}
/*
* NEC address=0xFB0C, command=0x18
*
* This is data 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.
* With the uint16_t format, you are able to modify the timings to meet the standards,
* 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[] PROGMEM
= { 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,
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*/};
void loop() {
#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
/*
* 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.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
#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.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
Serial.println(F("Send NEC 16 bit address 0x0102, 8 bit data 0x34 with generated timing"));
Serial.flush();
IrSender.sendNEC(0x0102, 0x34, true, 0);
delay(3000);
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,111 @@
/*
* SimpleReceiver.cpp
*
* Demonstrates receiving NEC IR codes with IRrecv
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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.
*
************************************************************************************
*/
/*
* Specify which protocol(s) should be used for decoding.
* If no protocol is defined, all protocols are active.
*/
//#define DECODE_DENON // Includes Sharp
//#define DECODE_JVC
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // the same as 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_DISTANCE // universal decoder for pulse distance protocols
//#define DECODE_HASH // special decoder for all protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <Arduino.h>
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
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.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}
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()) {
// Print a short summary of received data
IrReceiver.printIRResultShort(&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
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
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
}
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,87 @@
/*
* SimpleSender.cpp
*
* Demonstrates sending IR codes in standard format with address and command
* An extended example for sending can be found as SendDemo.
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* MIT License
*/
#include <Arduino.h>
//#define SEND_PWM_BY_TIMER
//#define USE_NO_SEND_PWM
//#define NO_LED_FEEDBACK_CODE // saves 418 bytes program memory
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
/*
* The IR library setup. That's all!
*/
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
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(IR_SEND_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.
*/
uint16_t sAddress = 0x0102;
uint8_t sCommand = 0x34;
uint8_t sRepeats = 0;
void loop() {
/*
* Print current send values
*/
Serial.println();
Serial.print(F("Send now: address=0x"));
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.print(sRepeats);
Serial.println();
Serial.println(F("Send NEC with 16 bit address"));
Serial.flush();
// Results for the first loop to: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
IrSender.sendNEC(sAddress, sCommand, sRepeats);
/*
* If you cannot avoid to send a raw value directly like e.g. 0xCB340102 you must use sendNECRaw()
*/
// Serial.println(F("Send NECRaw 0xCB340102"));
// IrSender.sendNECRaw(0xCB340102, sRepeats);
/*
* Increment send values
* Also increment address just for demonstration, which normally makes no sense
*/
sAddress += 0x0101;
sCommand += 0x11;
sRepeats++;
// clip repeats at 4
if (sRepeats > 4) {
sRepeats = 4;
}
delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
}

View File

@@ -0,0 +1,286 @@
/*
* 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-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if 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 13 // D7
#define APPLICATION_PIN 0 // D3
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(ESP32)
#include <Arduino.h>
// 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 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) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_SEND_PIN PA7
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". saves 370 bytes program memory and 38 bytes RAM for digistump core
#define IR_RECEIVE_PIN 0
#define IR_SEND_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
#define _IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // 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)
#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
#define _IR_TIMING_TEST_PIN 10 // PA4
# else
#define IR_RECEIVE_PIN 3
#define IR_SEND_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#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 3 // INT1
#define IR_SEND_PIN 4
#define TONE_PIN 9
#define _IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // Tiny Core Dev board
#define IR_RECEIVE_PIN 18
#define IR_SEND_PIN 19
#define TONE_PIN 20
#define APPLICATION_PIN 0 // PA4
#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 2 // PA6
#elif defined(__AVR_ATtiny1604__)
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define APPLICATION_PIN 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_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
#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
#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 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16
#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) // !!!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)
#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(__AVR__) // Default as for ATmega328 like on Uno, Nano 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
#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)
#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
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND 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)
#endif

View File

@@ -0,0 +1,429 @@
/*
* UnitTest.cpp
*
* Demonstrates sending IR codes in standard format with address and command and
* simultaneously receiving. Both values are checked for consistency.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 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 <Arduino.h>
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS
//#define SEND_PWM_BY_TIMER
//#define USE_NO_SEND_PWM
#define NO_LED_FEEDBACK_CODE // saves 500 bytes program memory
#define MARK_EXCESS_MICROS 10 // Adapt it to your IR receiver module. See also IRremote.h.
//#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_NEC // Includes Apple and Onkyo
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
#define DECODE_JVC
#define DECODE_RC5
#define DECODE_RC6
#define DECODE_SONY
#define DECODE_PANASONIC // the same as DECODE_KASEIKYO
#define DECODE_DISTANCE // universal decoder for pulse distance protocols
#define DECODE_HASH // special decoder for all protocols
#endif
#if FLASHEND >= 0x7FFF // For 32k flash or more, like ATmega328
#define DECODE_SAMSUNG
#define DECODE_LG
#define DECODE_BOSEWAVE
#define DECODE_LEGO_PF
#define DECODE_MAGIQUEST
#define DECODE_WHYNTER
#endif
#include "PinDefinitionsAndMore.h" //Define macros for input and output pin etc.
#include <IRremote.hpp>
#if defined(APPLICATION_PIN)
#define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data
#else
#define DEBUG_BUTTON_PIN 6
#endif
#define DELAY_AFTER_SEND 1000
#define DELAY_AFTER_LOOP 5000
#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
#endif
void setup() {
pinMode(DEBUG_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)
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);
IrSender.begin(IR_SEND_PIN, ENABLE_LED_FEEDBACK); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
// For esp32 we use PWM generation by ledcWrite() for each pin.
# if !defined(SEND_PWM_BY_TIMER)
/*
* Print internal software PWM generation info
*/
IrSender.enableIROut(38); // Call it with 38 kHz to initialize the values printed below
Serial.print(F("Send signal mark duration for 38kHz is "));
Serial.print(IrSender.periodOnTimeMicros);
Serial.print(F(" us, pulse correction is "));
Serial.print(IrSender.getPulseCorrectionNanos());
Serial.print(F(" ns, total period is "));
Serial.print(IrSender.periodTimeMicros);
Serial.println(F(" us"));
# endif
// 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"));
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
#endif
}
void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
// wait until signal has received
delay((RECORD_GAP_MICROS / 1000) + 1);
if (IrReceiver.decode()) {
// Print a short summary of received data
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
IrReceiver.printIRResultShort(&Serial);
#else
IrReceiver.printIRResultMinimal(&Serial);
#endif
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
IrReceiver.decodedIRData.flags = false; // yes we have recognized the flag :-)
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#modifying-compile-options-with-sloeber-ide } else {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
} else if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
#endif
} else {
/*
* Check address
*/
if (IrReceiver.decodedIRData.address != aSentAddress) {
Serial.print(F("ERROR: Received address=0x"));
Serial.print(IrReceiver.decodedIRData.address, HEX);
Serial.print(F(" != sent address=0x"));
Serial.println(aSentAddress, HEX);
}
/*
* Check command
*/
if (IrReceiver.decodedIRData.command != aSentCommand) {
Serial.print(F("ERROR: Received command=0x"));
Serial.print(IrReceiver.decodedIRData.command, HEX);
Serial.print(F(" != sent command=0x"));
Serial.println(aSentCommand, HEX);
}
}
IrReceiver.resume();
} else {
Serial.println(F("No data received"));
}
Serial.println();
}
/*
* 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.
*/
uint16_t sAddress = 0xFFF1;
uint8_t sCommand = 0x76;
#define sRepeats 0 // no unit test for repeats
void loop() {
/*
* Print values
*/
Serial.println();
Serial.print(F("address=0x"));
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.println();
Serial.println();
Serial.println(F("Send NEC with 8 bit address"));
Serial.flush();
IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats);
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);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
if (sAddress == 0xFFF1) {
/*
* 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"));
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 */
"0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */
"0017 003E 0017 0015 0017 003F 0017 0015 0017 0015 0017 0015 0017 003F 0017 0015 " /* command byte */
"0019 0013 0019 003C 0017 0015 0017 003F 0017 003E 0017 003F 0017 0015 0017 003E " /* inverted command byte */
"0017 0806"), 0); //stop bit, no repeat possible, because of missing repeat pattern
checkReceive(0x80, 0x45);
delay(DELAY_AFTER_SEND);
# if FLASHEND >= 0x7FFF // For 32k flash or more, like UNO. Code does not fit in program memory of ATtiny1604 etc.
Serial.println(F("Send NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)"));
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.
checkReceive(0xFB04 & 0xFF, 0x08);
delay(DELAY_AFTER_SEND);
# endif
/*
* With sendNECRaw() you can send 32 bit combined codes
*/
Serial.println(F("Send NEC / ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)"));
Serial.flush();
IrSender.sendNECRaw(0x03040102, sRepeats);
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.
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
Serial.println(F("Send NEC with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first"));
Serial.flush();
IrSender.sendNECMSB(0x40802CD3, 32, false);
checkReceive(0x0102, 0x34);
delay(DELAY_AFTER_SEND);
}
#endif
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
Serial.flush();
IrSender.sendOnkyo(sAddress, sCommand << 8 | sCommand, sRepeats);
checkReceive(sAddress, sCommand << 8 | sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Apple"));
Serial.flush();
IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
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.flush();
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo_Denon variant"));
Serial.flush();
IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Denon"));
Serial.flush();
IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Denon/Sharp variant"));
Serial.flush();
IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats);
checkReceive(sAddress & 0x1F, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 8 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL);
checkReceive(sAddress & 0xFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL);
checkReceive(sAddress & 0x1FFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits
checkReceive(sAddress & 0x1F, sCommand & 0x3F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5X with 7.th MSB of command set"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40);
delay(DELAY_AFTER_SEND);
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);
/*
* Next example how to use the IrSender.write function
*/
IRData IRSendData;
// prepare data
IRSendData.address = sAddress;
IRSendData.command = sCommand;
IRSendData.flags = IRDATA_FLAGS_EMPTY;
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);
IRSendData.protocol = JVC; // switch protocol
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
IRSendData.protocol = LG;
IRSendData.command = sCommand << 8 | sCommand; // LG supports 16 bit command
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif // FLASHEND >= 0x3FFF
#if FLASHEND >= 0x7FFF // For 32k flash or more, like ATmega328
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif // FLASHEND >= 0x7FFF
/*
* LEGO 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.
// 210 + 540 = 750 should be received as 5/10 or 4/11 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);
delay(DELAY_AFTER_SEND);
/*
* Increment values
* Also increment address just for demonstration, which normally makes no sense
*/
sAddress += 0x0101;
sCommand += 0x11;
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
}

View File

@@ -0,0 +1,98 @@
START ../src/UnitTest.cpp from Jan 27 2022
Using library version 3.6.0
Ready to receive IR signals of protocols: NEC, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Whynter, Lego Power Functions, Bosewave , MagiQuest, Universal Distance, Hash at pin 3
Send signal mark duration for 38kHz is 8 us, pulse correction is 3000 ns, total period is 26 us
5000 us is the (minimum) gap, after which the start of a new IR packet is assumed
10 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
Send NEC with 16 bit address
Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
Sending 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 NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)
Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first
Send NEC / 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
Send NEC with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send Onkyo (NEC with 16 bit command)
Protocol=ONKYO Address=0xFFF1 Command=0x7676 Raw-Data=0x7676FFF1 32 bits LSB first
Send Apple
Protocol=APPLE Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first
Send Panasonic
Protocol=PANASONIC Address=0xFF1 Command=0x76 Extra=0x2002 Raw-Data=0x9976FF10 48 bits LSB first
Send Kaseikyo with 0x4711 as Vendor ID
Protocol=KASEIKYO Address=0xFF1 Command=0x76 Raw-Data=0x9A76FF13 48 bits LSB first
Send Kaseikyo_Denon variant
Protocol=KASEIKYO_DENON Address=0xFF1 Command=0x76 Extra=0x3256 Raw-Data=0x9976FF10 48 bits LSB first
Send Denon
Protocol=DENON Address=0x11 Command=0x76 Raw-Data=0x45D8 15 bits MSB first
Send Denon/Sharp variant
Protocol=SHARP Address=0x11 Command=0x76 Raw-Data=0x45DA 15 bits MSB first
Send Sony/SIRCS with 7 command and 5 address bits
Protocol=SONY Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
Send Sony/SIRCS with 7 command and 8 address bits
Protocol=SONY Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first
Send Sony/SIRCS with 7 command and 13 address bits
Protocol=SONY Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first
Send RC5
Protocol=RC5 Address=0x11 Command=0x36 Toggle=1 Raw-Data=0x1C76 13 bits MSB first
Send RC5X with 7.th MSB of command set
Protocol=RC5 Address=0x11 Command=0x76 Raw-Data=0x476 13 bits MSB first
Send RC6
Protocol=RC6 Address=0xF1 Command=0x76 Toggle=1 Raw-Data=0x1F176 20 bits MSB first
Send SAMSUNG
Protocol=SAMSUNG Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
Send JVC
Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first
Send LG
Protocol=LG Address=0xF1 Command=0x7676 Raw-Data=0xF17676A 28 bits MSB first
Send Bosewave with no address and 8 command bits
Protocol=BOSEWAVE Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
Force buffer overflow by sending 280 marks and spaces
Protocol=UNKNOWN Hash=0x0 0 bits (incl. gap and start) received
Overflow detected
Try to increase the "RAW_BUFFER_LENGTH" value of 112 in ../src/UnitTest.cpp
address=0xF2 command=0x87
Send NEC with 8 bit address
Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
Send NEC with 16 bit address
Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
Send Onkyo (NEC with 16 bit command)
Protocol=ONKYO Address=0xF2 Command=0x8787 Raw-Data=0x878700F2 32 bits LSB first
Send Apple
Protocol=APPLE Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first

View File

@@ -0,0 +1,102 @@
#######################################
# Syntax Coloring Map For IRremote
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
decode_results KEYWORD1
IRrecv KEYWORD1
IRsend KEYWORD1
IrReceiver KEYWORD1
IrSender KEYWORD1
decodedIRData KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
setFeedbackLED KEYWORD2
enableLEDFeedback KEYWORD2
enableLEDFeedbackForSend KEYWORD2
disableLEDFeedback KEYWORD2
disableLEDFeedbackForSend KEYWORD2
printIRResultShort KEYWORD2
begin KEYWORD2
start KEYWORD2
available KEYWORD2
read KEYWORD2
stop KEYWORD2
end KEYWORD2
enableLEDFeedback KEYWORD2
decode KEYWORD2
resume KEYWORD2
enableIRIn KEYWORD2
disableIRIn KEYWORD2
sendNEC KEYWORD2
setSendPin KEYWORD2
write KEYWORD2
enableIROut KEYWORD2
IRLedOff KEYWORD2
sendRaw KEYWORD2
sendJVC KEYWORD2
sendLG KEYWORD2
sendLGRepeat KEYWORD2
sendLGRaw KEYWORD2
sendNEC KEYWORD2
sendNECRepeat KEYWORD2
sendNECRaw KEYWORD2
sendOnkyo KEYWORD2
sendApple KEYWORD2
sendPanasonic KEYWORD2
sendKaseikyo KEYWORD2
sendKaseikyo_Denon KEYWORD2
sendKaseikyo_Sharp KEYWORD2
sendKaseikyo_JVC KEYWORD2
sendKaseikyo_Mitsubishi KEYWORD2
sendRC5 KEYWORD2
sendRC6 KEYWORD2
sendSamsungRepeat KEYWORD2
sendSamsung KEYWORD2
sendSharp KEYWORD2
sendSony KEYWORD2
sendSharpRaw KEYWORD2
sendLegoPowerFunctions KEYWORD2
sendMagiQuest KEYWORD2
sendPronto KEYWORD2
sendMagiQuest KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
PULSE_DISTANCE LITERAL1
PULSE_WIDTH LITERAL1
DENON LITERAL1
DISH LITERAL1
JVC LITERAL1
LG LITERAL1
LG2 LITERAL1
NEC LITERAL1
PANASONIC LITERAL1
KASEIKYO LITERAL1
KASEIKYO_JVC LITERAL1
KASEIKYO_DENON LITERAL1
KASEIKYO_SHARP LITERAL1
KASEIKYO_MITSUBISHI LITERAL1
RC5 LITERAL1
RC6 LITERAL1
SAMSUNG LITERAL1
SHARP LITERAL1
SONY LITERAL1
ONKYO LITERAL1
APPLE LITERAL1
BOSEWAVE LITERAL1
LEGO_PF LITERAL1
MAGIQUEST LITERAL1
WHYNTER LITERAL1
UNKNOWN LITERAL1
IR_RECEIVE_PIN LITERAL1
IR_SEND_PIN LITERAL1
FEEDBACK_LED_IS_ACTIVE_LOW LITERAL1

View File

@@ -0,0 +1,29 @@
{
"name": "IRremote",
"keywords": "communication, infrared, ir, remote",
"description": "Send and receive infrared signals with multiple protocols",
"repository":
{
"type": "git",
"url": "https://github.com/z3t0/Arduino-IRremote.git"
},
"version": "3.7.1",
"frameworks": "arduino",
"platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
"authors" :
[
{
"name":"Armin Joachimsmeyer",
"email":"armin.arduino@gmail.com"
},
{
"name":"Rafi Khan",
"email":"rafi@rafikhan.io"
},
{
"name":"Ken Shirriff",
"email":"ken.shirriff@gmail.com"
}
],
"headers": "IRRemote.hpp"
}

View File

@@ -0,0 +1,10 @@
name=IRremote
version=3.7.1
author=shirriff, z3t0, ArminJo
maintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>
sentence=Send and receive infrared signals with multiple protocols
paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BoseWave, Lego, Whynter, MagiQuest.<br/><br/><b>New: </b>Minor improvements, changed types to fast ones and improved MagiQuest protocol.<br/><a href="https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md">Release notes</a><br/>
category=Communication
url=https://github.com/Arduino-IRremote/Arduino-IRremote
architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040
includes=IRremote.hpp

View File

@@ -0,0 +1,161 @@
/**
* @file IRFeedbackLED.hpp
*
* @brief All Feedback LED specific functions are contained in this file.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
*************************************************************************************
* MIT License
*
* Copyright (c) 2021-2022 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_FEEDBACK_LED_HPP
#define _IR_FEEDBACK_LED_HPP
/** \addtogroup FeedbackLEDFunctions Feedback LED functions
* @{
*/
#include "digitalWriteFast.h"
/**
* Contains pin number and enable status of the feedback LED
*/
struct FeedbackLEDControlStruct {
uint8_t FeedbackLEDPin; ///< if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
uint8_t LedFeedbackEnabled; ///< LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of pin on IR processing
};
struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED control instance
/**
* Enable blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving
* Cannot disable it here!!! Use disableLEDFeedbackForReceive() or disableLEDFeedbackForSend()
* @param aFeedbackLEDPin If aFeedbackLEDPin == 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
* If FeedbackLEDPin == 0 and no LED_BUILTIN defined, disable LED feedback
* @param aEnableLEDFeedback If LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of Feedback LED
*/
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback) {
FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; // default is 0 -> use LED_BUILTIN if available, else disable feedback
if (aEnableLEDFeedback != DO_NOT_ENABLE_LED_FEEDBACK) {
FeedbackLEDControl.LedFeedbackEnabled |= aEnableLEDFeedback;
if (aFeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
pinMode(aFeedbackLEDPin, OUTPUT);
#if defined(LED_BUILTIN)
} else {
pinMode(LED_BUILTIN, OUTPUT);
#else
FeedbackLEDControl.LedFeedbackEnabled = LED_FEEDBACK_DISABLED_COMPLETELY; // we have no LED_BUILTIN available
#endif
}
}
}
/*
* Direct replacement for blink13()
*/
void setLEDFeedback(bool aEnableLEDFeedback) {
bool tEnableLEDFeedback = LED_FEEDBACK_DISABLED_COMPLETELY;
if (aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND | LED_FEEDBACK_ENABLED_FOR_RECEIVE;
}
setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, tEnableLEDFeedback);
}
void enableLEDFeedback() {
FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_RECEIVE;
}
void disableLEDFeedback() {
FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_RECEIVE);
}
void enableLEDFeedbackForSend() {
FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_SEND;
}
void disableLEDFeedbackForSend() {
FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_SEND);
}
/**
* Flash LED while receiving or sending IR data. Does not check if enabled, this must be done by the caller.
* Handles the 0 value of FeedbackLEDPin and the macro FEEDBACK_LED_IS_ACTIVE_LOW.
*/
#if defined(ESP32) || defined(ESP8266)
IRAM_ATTR
#endif
void setFeedbackLED(bool aSwitchLedOn) {
if (aSwitchLedOn) {
if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED on
#else
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED on
#endif
#if defined(LED_BUILTIN) // use fast macros here
} else {
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
# else
digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
# endif
#endif
}
} else {
if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED off
#else
digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED off
#endif
#if defined(LED_BUILTIN) // use fast macros here
} else {
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
# else
digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
# endif
#endif
}
}
}
/**
* Old deprecated function name for setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()
*/
void IRrecv::blink13(uint8_t aEnableLEDFeedback) {
setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, aEnableLEDFeedback);
}
/**
* Old deprecated function name for setLEDFeedback()
*/
void setBlinkPin(uint8_t aBlinkPin) {
setLEDFeedback(aBlinkPin, FeedbackLEDControl.LedFeedbackEnabled);
}
/** @}*/
#endif // _IR_FEEDBACK_LED_HPP

View File

@@ -0,0 +1,103 @@
/**
* @file IRProtocol.h
* @brief Common declarations for receiving and sending.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_PROTOCOL_H
#define _IR_PROTOCOL_H
/**
* An enum consisting of all supported formats.
* You do NOT need to remove entries from this list when disabling protocols!
*/
typedef enum {
UNKNOWN = 0,
PULSE_DISTANCE,
PULSE_WIDTH,
DENON,
DISH,
JVC,
LG,
LG2,
NEC,
PANASONIC,
KASEIKYO,
KASEIKYO_JVC,
KASEIKYO_DENON,
KASEIKYO_SHARP,
KASEIKYO_MITSUBISHI,
RC5,
RC6,
SAMSUNG,
SHARP,
SONY,
ONKYO,
APPLE,
BOSEWAVE,
LEGO_PF,
MAGIQUEST,
WHYNTER,
} decode_type_t;
const __FlashStringHelper* getProtocolString(decode_type_t aProtocol);
#define PROTOCOL_IS_LSB_FIRST false
#define PROTOCOL_IS_MSB_FIRST true
/*
* Carrier frequencies for various protocols
*/
#define SONY_KHZ 40
#define BOSEWAVE_KHZ 38
#define DENON_KHZ 38
#define JVC_KHZ 38
#define LG_KHZ 38
#define NEC_KHZ 38
#define SAMSUNG_KHZ 38
#define KASEIKYO_KHZ 37
#define RC5_RC6_KHZ 36
/*
* Constants for some protocols
*/
#define PANASONIC_VENDOR_ID_CODE 0x2002
#define DENON_VENDOR_ID_CODE 0x3254
#define MITSUBISHI_VENDOR_ID_CODE 0xCB23
#define SHARP_VENDOR_ID_CODE 0x5AAA
#define JVC_VENDOR_ID_CODE 0x0103
#define SIRCS_12_PROTOCOL 12
#define SIRCS_15_PROTOCOL 15
#define SIRCS_20_PROTOCOL 20
#define LEGO_MODE_EXTENDED 0
#define LEGO_MODE_COMBO 1
#define LEGO_MODE_SINGLE 0x4 // here the 2 LSB have meanings like Output A / Output B
#endif // _IR_PROTOCOL_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,645 @@
/*
* IRSend.hpp
*
* Contains common functions for sending
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2022 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_SEND_HPP
#define _IR_SEND_HPP
/*
* This improves readability of code by avoiding a lot of #if defined clauses
*/
#if defined(IR_SEND_PIN)
#define sendPin IR_SEND_PIN
#endif
#include "digitalWriteFast.h"
/** \addtogroup Sending Sending IR data for multiple protocols
* @{
*/
// The sender instance
IRsend IrSender;
IRsend::IRsend() { // @suppress("Class members should be properly initialized")
#if !defined(IR_SEND_PIN)
sendPin = 0;
#endif
#if !defined(NO_LED_FEEDBACK_CODE)
setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
#endif
}
#if defined(IR_SEND_PIN)
/**
* Simple start with defaults - LED feedback enabled! Used if IR_SEND_PIN is defined. Saves program memory.
*/
void IRsend::begin(){
# if !defined(NO_LED_FEEDBACK_CODE)
setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
# endif
}
/**
* @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
*/
void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
#if !defined(NO_LED_FEEDBACK_CODE)
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
if(aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
}
setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
#else
(void) aEnableLEDFeedback;
(void) aFeedbackLEDPin;
#endif
}
#else // defined(IR_SEND_PIN)
IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be properly initialized")
sendPin = aSendPin;
# if !defined(NO_LED_FEEDBACK_CODE)
setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
# endif
}
/**
* Initializes the send pin and enable LED feedback with board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
* @param aSendPin The Arduino pin number, where a IR sender diode is connected.
*/
void IRsend::begin(uint_fast8_t aSendPin) {
sendPin = aSendPin;
# if !defined(NO_LED_FEEDBACK_CODE)
setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
# endif
}
void IRsend::setSendPin(uint_fast8_t aSendPin) {
sendPin = aSendPin;
}
#endif // defined(IR_SEND_PIN)
/**
* Initializes the send and feedback pin
* @param aSendPin The Arduino pin number, where a IR sender diode is connected.
* @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
*/
void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
#if defined(IR_SEND_PIN)
(void) aSendPin; // for backwards compatibility
#else
sendPin = aSendPin;
#endif
#if !defined(NO_LED_FEEDBACK_CODE)
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
if (aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
}
setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
#else
(void) aEnableLEDFeedback;
(void) aFeedbackLEDPin;
#endif
}
/**
* @param aIRSendData The values of protocol, address, command and repeat flag are taken for sending.
* @param aNumberOfRepeats Number of repeats to send after the initial data.
*/
size_t IRsend::write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats) {
auto tProtocol = aIRSendData->protocol;
auto tAddress = aIRSendData->address;
auto tCommand = aIRSendData->command;
bool tSendRepeat = (aIRSendData->flags & IRDATA_FLAGS_IS_REPEAT);
// switch (tProtocol) { // 26 bytes bigger than if, else if, else
// case NEC:
// sendNEC(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
// break;
// case SAMSUNG:
// sendSamsung(tAddress, tCommand, aNumberOfRepeats);
// break;
// case SONY:
// sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
// break;
// case PANASONIC:
// sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
// break;
// case DENON:
// sendDenon(tAddress, tCommand, aNumberOfRepeats);
// break;
// case SHARP:
// sendSharp(tAddress, tCommand, aNumberOfRepeats);
// break;
// case JVC:
// sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
// break;
// case RC5:
// sendRC5(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
// break;
// case RC6:
// // No toggle for repeats// sendRC6(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
// break;
// default:
// break;
// }
/*
* Order of protocols is in guessed relevance :-)
*/
if (tProtocol == NEC) {
sendNEC(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
} else if (tProtocol == SAMSUNG) {
sendSamsung(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == SONY) {
sendSony(tAddress, tCommand, aNumberOfRepeats, aIRSendData->numberOfBits);
} else if (tProtocol == PANASONIC) {
sendPanasonic(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == DENON) {
sendDenon(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == SHARP) {
sendSharp(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == LG) {
sendLG(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
} else if (tProtocol == JVC) {
sendJVC((uint8_t) tAddress, (uint8_t) tCommand, aNumberOfRepeats); // casts are required to specify the right function
} else if (tProtocol == RC5) {
sendRC5(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
} else if (tProtocol == RC6) {
sendRC6(tAddress, tCommand, aNumberOfRepeats, !tSendRepeat); // No toggle for repeats
} else if (tProtocol == KASEIKYO_JVC) {
sendKaseikyo_JVC(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == KASEIKYO_DENON) {
sendKaseikyo_Denon(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == KASEIKYO_SHARP) {
sendKaseikyo_Sharp(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == KASEIKYO_MITSUBISHI) {
sendKaseikyo_Mitsubishi(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == ONKYO) {
sendOnkyo(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
} else if (tProtocol == APPLE) {
sendApple(tAddress, tCommand, aNumberOfRepeats, tSendRepeat);
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
} else if (tProtocol == BOSEWAVE) {
sendBoseWave(tCommand, aNumberOfRepeats);
} else if (tProtocol == LEGO_PF) {
sendLegoPowerFunctions(tAddress, tCommand, tCommand >> 4, tSendRepeat); // send 5 autorepeats
#endif
}
return 1;
}
/**
* Function using an 16 byte microsecond timing array for every purpose.
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
/*
* Raw data starts with a mark.
*/
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
if (i & 1) {
// Odd
space(aBufferWithMicroseconds[i]);
} else {
mark(aBufferWithMicroseconds[i]);
}
}
IrReceiver.restartAfterSend();
}
/**
* New function using an 8 byte tick timing array to save program memory
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
if (i & 1) {
// Odd
space(aBufferWithTicks[i] * MICROS_PER_TICK);
} else {
mark(aBufferWithTicks[i] * MICROS_PER_TICK);
}
}
IRLedOff(); // Always end with the LED off
IrReceiver.restartAfterSend();
}
/**
* Function using an 16 byte microsecond timing array in FLASH for every purpose.
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
#if !defined(__AVR__)
sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
#else
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
/*
* Raw data starts with a mark
*/
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
unsigned int duration = pgm_read_word(&aBufferWithMicroseconds[i]);
if (i & 1) {
// Odd
space(duration);
} else {
mark(duration);
}
}
IrReceiver.restartAfterSend();
#endif
}
/**
* New function using an 8 byte tick timing array in FLASH to save program memory
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
#if !defined(__AVR__)
sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
#else
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
unsigned int duration = pgm_read_byte(&aBufferWithTicks[i]) * (unsigned int) MICROS_PER_TICK;
if (i & 1) {
// Odd
space(duration);
} else {
mark(duration);
}
}
IRLedOff(); // Always end with the LED off
IrReceiver.restartAfterSend();
#endif
}
/**
* Sends PulseDistance data
* The output always ends with a space
*/
void IRsend::sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
unsigned int aZeroSpaceMicros, uint32_t aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit) {
if (aMSBfirst) { // Send the MSB first.
// send data from MSB to LSB until mask bit is shifted out
for (uint32_t tMask = 1UL << (aNumberOfBits - 1); tMask; tMask >>= 1) {
if (aData & tMask) {
IR_TRACE_PRINT('1');
mark(aOneMarkMicros);
space(aOneSpaceMicros);
} else {
IR_TRACE_PRINT('0');
mark(aZeroMarkMicros);
space(aZeroSpaceMicros);
}
}
} else { // Send the Least Significant Bit (LSB) first / MSB last.
for (uint_fast8_t bit = 0; bit < aNumberOfBits; bit++, aData >>= 1)
if (aData & 1) { // Send a 1
IR_TRACE_PRINT('1');
mark(aOneMarkMicros);
space(aOneSpaceMicros);
} else { // Send a 0
IR_TRACE_PRINT('0');
mark(aZeroMarkMicros);
space(aZeroSpaceMicros);
}
}
if (aSendStopBit) {
IR_TRACE_PRINT('S');
mark(aZeroMarkMicros); // seems like this is used for stop bits
}
IR_TRACE_PRINTLN(F(""));
}
/*
* Sends Biphase data MSB first
* Always send start bit, do not send the trailing space of the start bit
* 0 -> mark+space
* 1 -> space+mark
* The output always ends with a space
*/
void IRsend::sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
// do not send the trailing space of the start bit
mark(aBiphaseTimeUnit);
IR_TRACE_PRINT('S');
uint_fast8_t tLastBitValue = 1; // Start bit is a 1
// Data - Biphase code MSB first
for (uint32_t tMask = 1UL << (aNumberOfBits - 1); tMask; tMask >>= 1) {
if (aData & tMask) {
IR_TRACE_PRINT('1');
space(aBiphaseTimeUnit);
mark(aBiphaseTimeUnit);
tLastBitValue = 1;
} else {
IR_TRACE_PRINT('0');
#if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
if (tLastBitValue) {
// Extend the current mark in order to generate a continuous signal without short breaks
delayMicroseconds(aBiphaseTimeUnit);
} else {
mark(aBiphaseTimeUnit);
}
#else
(void) tLastBitValue; // to avoid compiler warnings
mark(aBiphaseTimeUnit); // can not eventually delay here, we must call mark to generate the signal
#endif
space(aBiphaseTimeUnit);
tLastBitValue = 0;
}
}
IR_TRACE_PRINTLN(F(""));
}
/**
* Sends an IR mark for the specified number of microseconds.
* The mark output is modulated at the PWM frequency if USE_NO_SEND_PWM is not defined.
* The output is guaranteed to be OFF / inactive after after the call of the function.
* This function may affect the state of feedback LED.
*/
void IRsend::mark(unsigned int aMarkMicros) {
#if defined(SEND_PWM_BY_TIMER)
# if !defined(NO_LED_FEEDBACK_CODE)
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(true);
}
# endif
ENABLE_SEND_PWM_BY_TIMER; // Enable timer or ledcWrite() generated PWM output
customDelayMicroseconds(aMarkMicros);
IRLedOff(); // manages also feedback LED
#elif defined(USE_NO_SEND_PWM)
# if !defined(NO_LED_FEEDBACK_CODE)
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(true);
}
# endif
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
# else
digitalWriteFast(sendPin, LOW); // Set output to active low.
# endif
customDelayMicroseconds(aMarkMicros);
IRLedOff();
# if !defined(NO_LED_FEEDBACK_CODE)
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(false);
}
# endif
#else
unsigned long startMicros = micros();
unsigned long nextPeriodEnding = startMicros;
unsigned long tMicros;
# if !defined(NO_LED_FEEDBACK_CODE)
bool FeedbackLedIsActive = false;
# endif
do {
// digitalToggleFast(_IR_TIMING_TEST_PIN);
// Output the PWM pulse
noInterrupts(); // do not let interrupts extend the short on period
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
# if defined(OUTPUT_OPEN_DRAIN)
digitalWriteFast(sendPin, LOW); // active state for open drain
# else
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
# endif
# else
// 3.5 us from FeedbackLed on to pin setting. 5.7 us from call of mark() to pin setting incl. setting of feedback pin.
// 4.3 us from do{ to pin setting if sendPin is no constant
digitalWriteFast(sendPin, HIGH);
# endif
delayMicroseconds (periodOnTimeMicros); // this is normally implemented by a blocking wait
// Output the PWM pause
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
# if defined(OUTPUT_OPEN_DRAIN)
digitalWriteFast(sendPin, HIGH); // Set output with pin mode OUTPUT_OPEN_DRAIN to inactive high.
# else
pinModeFast(sendPin, INPUT); // to mimic the open drain inactive state
# endif
# else
digitalWriteFast(sendPin, LOW);
# endif
interrupts(); // Enable interrupts -to keep micros correct- for the longer off period 3.4 us until receive ISR is active (for 7 us + pop's)
# if !defined(NO_LED_FEEDBACK_CODE)
/*
* Delayed call of setFeedbackLED() to get better timing
*/
if (!FeedbackLedIsActive) {
FeedbackLedIsActive = true;
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(true);
}
}
# endif
/*
* Pause timing
*/
nextPeriodEnding += periodTimeMicros;
do {
tMicros = micros(); // we have only 4 us resolution for AVR @16MHz
// check for aMarkMicros to be gone
unsigned int tDeltaMicros = tMicros - startMicros;
#if defined(__AVR__)
// tDeltaMicros += (160 / CLOCKS_PER_MICRO); // adding this once increases program size !
# if !defined(NO_LED_FEEDBACK_CODE)
if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) { // 30 to be constant. Using periodTimeMicros increases program size too much.
// reset feedback led in the last pause before end
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(false);
}
}
# endif
if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) { // To compensate for call duration - 112 is an empirical value
#else
if (tDeltaMicros >= aMarkMicros) {
# if !defined(NO_LED_FEEDBACK_CODE)
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(false);
}
# endif
#endif
return;
}
// digitalToggleFast(_IR_TIMING_TEST_PIN); // 3.0 us per call @16MHz
} while (tMicros < nextPeriodEnding); // 3.4 us @16MHz
} while (true);
# endif
}
/**
* Just switch the IR sending LED off to send an IR space
* A space is "no output", so the PWM output is disabled.
* This function may affect the state of feedback LED.
*/
void IRsend::IRLedOff() {
#if defined(SEND_PWM_BY_TIMER)
DISABLE_SEND_PWM_BY_TIMER; // Disable PWM output
#elif defined(USE_NO_SEND_PWM)
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
digitalWriteFast(sendPin, LOW); // prepare for all next active states.
pinModeFast(sendPin, INPUT); // inactive state for open drain
# else
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
# endif
#else
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
# if defined(OUTPUT_OPEN_DRAIN)
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
# else
pinModeFast(sendPin, INPUT); // inactive state to mimic open drain
# endif
# else
digitalWriteFast(sendPin, LOW);
# endif
#endif
#if !defined(NO_LED_FEEDBACK_CODE)
if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
setFeedbackLED(false);
}
#endif
}
/**
* Sends an IR space for the specified number of microseconds.
* A space is "no output", so just wait.
*/
void IRsend::space(unsigned int aSpaceMicros) {
customDelayMicroseconds(aSpaceMicros);
}
/**
* Custom delay function that circumvents Arduino's delayMicroseconds 16 bit limit
* and is (mostly) not extended by the duration of interrupt codes like the millis() interrupt
*/
void IRsend::customDelayMicroseconds(unsigned long aMicroseconds) {
#if defined(__AVR__)
unsigned long start = micros() - (64 / clockCyclesPerMicrosecond()); // - (64 / clockCyclesPerMicrosecond()) for reduced resolution and additional overhead
#else
unsigned long start = micros();
#endif
// overflow invariant comparison :-)
while (micros() - start < aMicroseconds) {
}
}
/**
* Enables IR output. The kHz value controls the modulation frequency in kilohertz.
* The IR output will be on pin 3 (OC2B).
* This routine is designed for 36-40 kHz and for software generation gives 26 us for 38.46 kHz, 27 us for 37.04 kHz and 25 us for 40 kHz.
* If you use it for other values, it's up to you to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
* TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
* controlling the duty cycle.
* There is no prescaling, so the output frequency is 16 MHz / (2 * OCR2A)
* To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
* A few hours staring at the ATmega documentation and this will all make sense.
* See my Secrets of Arduino PWM at http://www.righto.com/2009/07/secrets-of-arduino-pwm.html for details.
*/
void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER)
timerConfigForSend(aFrequencyKHz); // must set output pin mode and disable receive interrupt if required, e.g. uses the same resource
#elif defined(USE_NO_SEND_PWM)
(void) aFrequencyKHz;
#else
periodTimeMicros = (1000U + (aFrequencyKHz / 2)) / aFrequencyKHz; // rounded value -> 26 for 38.46 kHz, 27 for 37.04 kHz, 25 for 40 kHz.
# if defined(IR_SEND_PIN)
periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50) / 100U); // +50 for rounding -> 830/100 for 30% and 16 MHz
# else
// Heuristics! We require a nanosecond correction for "slow" digitalWrite() functions
periodOnTimeMicros = (((periodTimeMicros * IR_SEND_DUTY_CYCLE_PERCENT) + 50 - (PULSE_CORRECTION_NANOS / 10)) / 100U); // +50 for rounding -> 530/100 for 30% and 16 MHz
# endif
#endif // defined(SEND_PWM_BY_TIMER)
#if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && defined(OUTPUT_OPEN_DRAIN) // the mode INPUT for mimicking open drain is set at IRLedOff()
# if defined(IR_SEND_PIN)
pinModeFast(IR_SEND_PIN, OUTPUT_OPEN_DRAIN);
# else
pinModeFast(sendPin, OUTPUT_OPEN_DRAIN);
# endif
#else
# if !(defined(SEND_PWM_BY_TIMER) && defined(ESP32)) // ledcWrite since ESP 2.0.2 does not work if pin mode is set
# if defined(IR_SEND_PIN)
pinModeFast(IR_SEND_PIN, OUTPUT);
# else
pinModeFast(sendPin, OUTPUT);
# endif
# endif
#endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
}
unsigned int IRsend::getPulseCorrectionNanos() {
return PULSE_CORRECTION_NANOS;
}
/** @}*/
#endif // _IR_SEND_HPP

View File

@@ -0,0 +1,14 @@
/**
* @file IRremote.h
*
* @brief Stub for backward compatibility
*/
#ifndef IRremote_h
#define IRremote_h
#include "IRremote.hpp"
#endif // IRremote_h
#pragma once

View File

@@ -0,0 +1,357 @@
/**
* @file IRremote.hpp
*
* @brief Public API to the library.
*
* @code
* !!! All the macro values defined here can be overwritten with values, !!!
* !!! the user defines in its source code BEFORE the #include <IRremote.hpp> !!!
* @endcode
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2015-2022 Ken Shirriff http://www.righto.com, Rafi Khan, 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.
*
************************************************************************************
*
* For Ken Shiriffs original blog entry, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
* Initially influenced by:
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* and http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*/
/*
* This library can be configured at compile time by the following options / macros:
* For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
*
* - RAW_BUFFER_LENGTH Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits.
* - IR_SEND_PIN If specified (as constant), reduces program size and improves send timing for AVR.
* - SEND_PWM_BY_TIMER Disable carrier PWM generation in software and use (restricted) hardware PWM.
* - USE_NO_SEND_PWM Use no carrier PWM, just simulate an **active low** receiver signal. Overrides SEND_PWM_BY_TIMER definition.
* - 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!
* - EXCLUDE_EXOTIC_PROTOCOLS If activated, BOSEWAVE, WHYNTER and LEGO_PF are excluded in decode() and in sending with IrSender.write().
* - EXCLUDE_UNIVERSAL_PROTOCOLS If activated, the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) are excluded in decode().
* - DECODE_* Selection of individual protocols to be decoded. See below.
* - MARK_EXCESS_MICROS Value 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 Minimum gap between IR transmissions, to detect the end of a protocol.
* - FEEDBACK_LED_IS_ACTIVE_LOW Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low.
* - NO_LED_FEEDBACK_CODE This completely disables the LED feedback code for send and receive.
* - IR_INPUT_IS_ACTIVE_HIGH Enable it if you use a RF receiver, which has an active HIGH output signal.
* - IR_SEND_DUTY_CYCLE_PERCENT Duty cycle of IR send signal.
* - MICROS_PER_TICK Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 us at 38 kHz.
* - IR_USE_AVR_TIMER* Selection of timer to be used for generating IR receiving sample interval.
*/
#ifndef _IR_REMOTE_HPP
#define _IR_REMOTE_HPP
#define VERSION_IRREMOTE "3.7.1"
#define VERSION_IRREMOTE_MAJOR 3
#define VERSION_IRREMOTE_MINOR 7
#define VERSION_IRREMOTE_PATCH 1
/*
* Macro to convert 3 version parts into an integer
* To be used in preprocessor comparisons, such as #if VERSION_IRREMOTE_HEX >= VERSION_HEX_VALUE(3, 7, 0)
*/
#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#define VERSION_IRREMOTE_HEX VERSION_HEX_VALUE(VERSION_IRREMOTE_MAJOR, VERSION_IRREMOTE_MINOR, VERSION_IRREMOTE_PATCH)
// activate it for all cores that does not use the -flto flag, if you get false error messages regarding begin() during compilation.
//#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN
/*
* If activated, BOSEWAVE, MAGIQUEST,WHYNTER and LEGO_PF are excluded in decoding and in sending with IrSender.write
*/
//#define EXCLUDE_EXOTIC_PROTOCOLS
/****************************************************
* PROTOCOLS
****************************************************/
/*
* Supported IR protocols
* Each protocol you include costs memory and, during decode, costs time
* Copy the lines with the protocols you need in your program before the #include <IRremote.hpp> line
* See also SimpleReceiver example
*/
#if !defined(NO_DECODER) // for sending raw only
# if (!(defined(DECODE_DENON) || defined(DECODE_JVC) || defined(DECODE_KASEIKYO) \
|| defined(DECODE_PANASONIC) || defined(DECODE_LG) || defined(DECODE_NEC) || defined(DECODE_SAMSUNG) \
|| defined(DECODE_SONY) || defined(DECODE_RC5) || defined(DECODE_RC6) \
|| defined(DECODE_DISTANCE) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
|| defined(DECODE_LEGO_PF) || defined(DECODE_WHYNTER)))
/*
* If no protocol is explicitly enabled, we enable all protocols
*/
#define DECODE_DENON // Includes Sharp
#define DECODE_JVC
#define DECODE_KASEIKYO
#define DECODE_PANASONIC // the same as DECODE_KASEIKYO
#define DECODE_LG
#define DECODE_NEC // Includes Apple and Onkyo
#define DECODE_SAMSUNG
#define DECODE_SONY
#define DECODE_RC5
#define DECODE_RC6
# if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory
#define DECODE_BOSEWAVE
#define DECODE_LEGO_PF
#define DECODE_WHYNTER
#define DECODE_MAGIQUEST // It modifies the RAW_BUFFER_LENGTH from 100 to 112
# endif
# if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS)
#define DECODE_DISTANCE // universal decoder for pulse distance protocols - requires up to 750 bytes additional program memory
#define DECODE_HASH // special decoder for all protocols - requires up to 250 bytes additional program memory
# endif
# endif
#endif // !defined(NO_DECODER)
#if defined(DECODE_NEC) && !(~(~DECODE_NEC + 0) == 0 && ~(~DECODE_NEC + 1) == 1)
#warning "The macros DECODE_XXX no longer require a value. Decoding is now switched by defining / non defining the macro."
#endif
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core.
/****************************************************
* RECEIVING
****************************************************/
/**
* The length of the buffer where the IR timing data is stored before decoding
* 100 is sufficient for most standard protocols, but air conditioners often send a longer protocol data stream
*/
#if !defined(RAW_BUFFER_LENGTH)
# if defined(DECODE_MAGIQUEST)
#define RAW_BUFFER_LENGTH 112 // MagiQuest requires 112 bytes.
# else
#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
//#define RAW_BUFFER_LENGTH 750 // 750 is the value for air condition remotes.
# endif
#endif
#if RAW_BUFFER_LENGTH % 2 == 1
#error RAW_BUFFER_LENGTH must be even, since the array consists of space / mark pairs.
#endif
/**
* 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
* For Vishay TSOP*, marks tend to be too long and spaces tend to be too short.
* If you set MARK_EXCESS_MICROS to approx. 50us then the TSOP4838 works best.
* At 100us it also worked, but not as well.
* Set MARK_EXCESS to 100us and the VS1838 doesn't work at all.
*
* The right value is critical for IR codes using short pulses like Denon / Sharp / Lego
*
* Observed values:
* Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level.
* VS1838 Mark Excess -50 to +50 us
* TSOP31238 Mark Excess 0 to +50
*/
#if !defined(MARK_EXCESS_MICROS)
// To change this value, you simply can add a line #define "MARK_EXCESS_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
#define MARK_EXCESS_MICROS 20
#endif
/**
* 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 us.
* 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.
*/
#if !defined(RECORD_GAP_MICROS)
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
#define RECORD_GAP_MICROS 5000 // FREDRICH28AC / LG2 header space is 9700, NEC header space is 4500
#endif
/**
* Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value.
*/
#if !defined(RECORD_GAP_MICROS_WARNING_THRESHOLD)
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS_WARNING_THRESHOLD <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
#define RECORD_GAP_MICROS_WARNING_THRESHOLD 20000
#endif
/** Minimum gap between IR transmissions, in MICROS_PER_TICK */
#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 221 for 1100
/*
* Activate this line if your receiver has an external output driver transistor / "inverted" output
*/
//#define IR_INPUT_IS_ACTIVE_HIGH
#if defined(IR_INPUT_IS_ACTIVE_HIGH)
// IR detector output is active high
#define INPUT_MARK 1 ///< Sensor output for a mark ("flash")
#else
// IR detector output is active low
#define INPUT_MARK 0 ///< Sensor output for a mark ("flash")
#endif
/****************************************************
* SENDING
****************************************************/
/**
* Define to disable carrier PWM generation in software and use (restricted) hardware PWM.
*/
//#define SEND_PWM_BY_TIMER // restricts send pin on many platforms to fixed pin numbers
#if (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED)
# if !defined(SEND_PWM_BY_TIMER)
#define SEND_PWM_BY_TIMER // the best and default method for ESP32
#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default. If this is not intended, deactivate the line over this warning message in file IRremote.hpp.
# endif
#else
# if defined(SEND_PWM_BY_TIMER)
# if defined(IR_SEND_PIN)
#undef IR_SEND_PIN // to avoid warning 3 lines later
#warning Since SEND_PWM_BY_TIMER is defined, the existing value of IR_SEND_PIN is discarded and replaced by the value determined by timer used for PWM generation
# endif
#define IR_SEND_PIN DeterminedByTimer // must be set here, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp
# endif
#endif
/**
* Define to use no carrier PWM, just simulate an active low receiver signal.
*/
//#define USE_NO_SEND_PWM
#if defined(SEND_PWM_BY_TIMER) && defined(USE_NO_SEND_PWM)
#warning "SEND_PWM_BY_TIMER and USE_NO_SEND_PWM are both defined -> undefine SEND_PWM_BY_TIMER now!"
#undef SEND_PWM_BY_TIMER // USE_NO_SEND_PWM overrides SEND_PWM_BY_TIMER
#endif
/**
* Define to 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_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
#if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
#warning Pin mode OUTPUT_OPEN_DRAIN is not supported on this platform -> fall back to mode OUTPUT.
#endif
/**
* This amount is subtracted from the on-time of the pulses generated for software PWM generation.
* It should be the time used for digitalWrite(sendPin, LOW) and the call to delayMicros()
* Measured value for Nano @16MHz is around 3000, for Bluepill @72MHz is around 700, for Zero 3600
*/
#if !defined(PULSE_CORRECTION_NANOS)
# if defined(F_CPU)
// To change this value, you simply can add a line #define "PULSE_CORRECTION_NANOS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
#define PULSE_CORRECTION_NANOS (48000L / (F_CPU/MICROS_IN_ONE_SECOND)) // 3000 @16MHz, 666 @72MHz
# else
#define PULSE_CORRECTION_NANOS 600
# endif
#endif
/**
* Duty cycle in percent for sent signals.
*/
#if ! defined(IR_SEND_DUTY_CYCLE_PERCENT)
#define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code
#endif
/**
* microseconds per clock interrupt tick
*/
#if ! defined(MICROS_PER_TICK)
#define MICROS_PER_TICK 50
#endif
#define MILLIS_IN_ONE_SECOND 1000L
#define MICROS_IN_ONE_SECOND 1000000L
#define MICROS_IN_ONE_MILLI 1000L
#include "IRremoteInt.h"
#if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
#include "private/IRTimer.hpp" // defines IR_SEND_PIN for AVR and SEND_PWM_BY_TIMER
# if !defined(NO_LED_FEEDBACK_CODE)
# if !defined(LED_BUILTIN)
/*
* print a warning
*/
#warning INFO: No definition for LED_BUILTIN found -> default LED feedback is disabled.
# endif
#include "IRFeedbackLED.hpp"
# endif
/*
* Include the sources here to enable compilation with macro values set by user program.
*/
#include "IRReceive.hpp"
#include "IRSend.hpp"
/*
* Include the sources of all decoders here to enable compilation with macro values set by user program.
*/
# if defined(DECODE_BOSEWAVE)
#include "ir_BoseWave.hpp"
# endif
# if defined(DECODE_DENON ) // Includes Sharp
#include "ir_Denon.hpp"
# endif
# if defined(DECODE_DISTANCE) // universal decoder for pulse distance protocols - requires up to 750 bytes additional program memory
#include "ir_DistanceProtocol.hpp"
# endif
# if defined(DECODE_JVC)
#include "ir_JVC.hpp"
# endif
# if defined(DECODE_KASEIKYO) || defined(DECODE_PANASONIC)
#include "ir_Kaseikyo.hpp"
# endif
# if defined(DECODE_LEGO_PF)
#include "ir_Lego.hpp"
# endif
# if defined(DECODE_LG)
#include "ir_LG.hpp"
# endif
# if defined(DECODE_MAGIQUEST)
#include "ir_MagiQuest.hpp"
# endif
# if defined(DECODE_NEC) // Includes Apple and Onkyo
#include "ir_NEC.hpp"
# endif
# if defined(DECODE_RC5) || defined(DECODE_RC6)
#include "ir_RC5_RC6.hpp"
# endif
# if defined(DECODE_SAMSUNG)
#include "ir_Samsung.hpp"
# endif
# if defined(DECODE_SONY)
#include "ir_Sony.hpp"
# endif
# if defined(DECODE_WHYNTER)
#include "ir_Whynter.hpp"
# endif
#include "ir_Pronto.hpp" // pronto is an universal decoder and encoder
#include "ir_Dish.hpp" // contains only sendDISH(unsigned long data, int nbits)
#endif // #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
/**
* Macros for legacy compatibility
*/
#define RAWBUF 101 // Maximum length of raw duration buffer
#define REPEAT 0xFFFFFFFF
#define USECPERTICK MICROS_PER_TICK
#define MARK_EXCESS MARK_EXCESS_MICROS
#endif // _IR_REMOTE_HPP

View File

@@ -0,0 +1,532 @@
/**
* @file IRremoteInt.h
* @brief Contains all declarations required for the interface to IRremote.
* Could not be named IRremote.h, since this has another semantic (it must include all *.hpp files) for old example code found in the wild.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
*
************************************************************************************
* MIT License
*
* Copyright (c) 2015-2022 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_REMOTE_INT_H
#define _IR_REMOTE_INT_H
#include <Arduino.h>
#define MARK 1
#define SPACE 0
#if defined(PARTICLE)
#define F_CPU 16000000 // definition for a board for which F_CPU is not defined
#endif
#if defined(F_CPU) // F_CPU is used to generate the receive send timings in some CPU's
#define CLOCKS_PER_MICRO (F_CPU / MICROS_IN_ONE_SECOND)
#endif
/*
* For backwards compatibility
*/
#if defined(SYSCLOCK) // allow for processor specific code to define F_CPU
#undef F_CPU
#define F_CPU SYSCLOCK // Clock frequency to be used for timing.
#endif
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
//#define TRACE // Activate this for more debug output.
/**
* For better readability of code
*/
#define DISABLE_LED_FEEDBACK false
#define ENABLE_LED_FEEDBACK true
#define USE_DEFAULT_FEEDBACK_LED_PIN 0
#include "IRProtocol.h"
/****************************************************
* Declarations for the receiver Interrupt Service Routine
****************************************************/
// ISR State-Machine : Receiver States
#define IR_REC_STATE_IDLE 0
#define IR_REC_STATE_MARK 1
#define IR_REC_STATE_SPACE 2
#define IR_REC_STATE_STOP 3 // set to IR_REC_STATE_IDLE only by resume()
/**
* This struct contains the data and control used for receiver static functions and the ISR (interrupt service routine)
* Only StateForISR needs to be volatile. All the other fields are not written by ISR after data available and before start/resume.
*/
struct irparams_struct {
// The fields are ordered to reduce memory over caused by struct-padding
volatile uint8_t StateForISR; ///< State Machine state
uint_fast8_t IRReceivePin; ///< Pin connected to IR data from detector
#if defined(__AVR__)
volatile uint8_t *IRReceivePinPortInputRegister;
uint8_t IRReceivePinMask;
#endif
uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition.
bool OverflowFlag; ///< Raw buffer OverflowFlag occurred
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t rawlen; ///< counter of entries in rawbuf
#else
uint_fast16_t rawlen; ///< counter of entries in rawbuf
#endif
unsigned int rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
};
/*
* Debug directives
*/
#if defined(DEBUG)
# define IR_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
# define IR_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
#else
/**
* If DEBUG, print the arguments, otherwise do nothing.
*/
# define IR_DEBUG_PRINT(...) void()
/**
* If DEBUG, print the arguments as a line, otherwise do nothing.
*/
# define IR_DEBUG_PRINTLN(...) void()
#endif
#if defined(TRACE)
# define IR_TRACE_PRINT(...) Serial.print(__VA_ARGS__)
# define IR_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
#else
# define IR_TRACE_PRINT(...) void()
# define IR_TRACE_PRINTLN(...) void()
#endif
/****************************************************
* RECEIVING
****************************************************/
/*
* Definitions for member IRData.flags
*/
#define IRDATA_FLAGS_EMPTY 0x00
#define IRDATA_FLAGS_IS_REPEAT 0x01
#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
#define IRDATA_TOGGLE_BIT_MASK 0x08 ///< is set if RC5 or RC6 toggle bit is set
#define IRDATA_FLAGS_EXTRA_INFO 0x10 ///< there is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID)
#define IRDATA_FLAGS_WAS_OVERFLOW 0x40 ///< irparams.rawlen is 0 in this case to avoid endless OverflowFlag
#define IRDATA_FLAGS_IS_LSB_FIRST 0x00
#define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Just for info. Value is mainly determined by the protocol
/**
* Data structure for the user application, available as decodedIRData.
* Filled by decoders and read by print functions or user application.
*/
struct IRData {
decode_type_t protocol; ///< UNKNOWN, NEC, SONY, RC5, ...
uint16_t address; ///< Decoded address
uint16_t command; ///< Decoded command
uint16_t extra; ///< Contains MagiQuest magnitude, Kaseikyo unknown vendor ID and Distance protocol (SpaceTicksShort << 8) | SpaceTicksLong.
uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; ///< See IRDATA_FLAGS_* definitions above
uint32_t decodedRawData; ///< Up to 32 bit decoded raw data, to be used for send functions.
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
};
/**
* Results returned from old decoders !!!deprecated!!!
*/
struct decode_results {
decode_type_t decode_type; // deprecated, moved to decodedIRData.protocol ///< UNKNOWN, NEC, SONY, RC5, ...
uint16_t address; ///< Used by Panasonic & Sharp [16-bits]
uint32_t value; // deprecated, moved to decodedIRData.decodedRawData ///< Decoded value / command [max 32-bits]
uint8_t bits; // deprecated, moved to decodedIRData.numberOfBits ///< Number of bits in decoded value
uint16_t magnitude; // deprecated, moved to decodedIRData.extra ///< Used by MagiQuest [16-bits]
bool isRepeat; // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected
// next 3 values are copies of irparams values - see IRremoteint.h
unsigned int *rawbuf; // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks
uint_fast8_t rawlen; // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf
bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long
};
/**
* Main class for receiving IR signals
*/
class IRrecv {
public:
IRrecv();
IRrecv(uint_fast8_t aReceivePin);
IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin);
void setReceivePin(uint_fast8_t aReceivePinNumber);
/*
* Stream like API
*/
void begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin =
USE_DEFAULT_FEEDBACK_LED_PIN);
void start();
void enableIRIn(); // alias for start
void start(uint32_t aMicrosecondsToAddToGapCounter);
void restartAfterSend();
bool available();
IRData* read(); // returns decoded data
// write is a method of class IRsend below
// size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void stop();
void disableIRIn(); // alias for stop
void end(); // alias for stop
bool isIdle();
/*
* The main functions
*/
bool decode(); // Check if available and try to decode
void resume(); // Enable receiving of the next value
/*
* Useful info and print functions
*/
void printIRResultShort(Print *aSerial);
void printIRResultMinimal(Print *aSerial);
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void printIRResultAsCVariables(Print *aSerial);
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int frequency = 38000U);
/*
* Store the data for further processing
*/
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr);
size_t compensateAndStorePronto(String *aString, unsigned int frequency = 38000U);
/*
* The main decoding functions used by the individual decoders
*/
bool decodePulseDistanceData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aBitMarkMicros,
unsigned int aOneSpaceMicros, unsigned int aZeroSpaceMicros, bool aMSBfirst);
bool decodePulseWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, unsigned int aOneMarkMicros,
unsigned int aZeroMarkMicros, unsigned int aBitSpaceMicros, bool aMSBfirst);
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
uint_fast8_t aValueOfSpaceToMarkTransition, unsigned int aBiphaseTimeUnit);
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, unsigned int aBiphaseTimeUnit);
uint_fast8_t getBiphaselevel();
/*
* All standard (decode address + command) protocol decoders
*/
bool decodeBoseWave();
bool decodeDenon();
bool decodeJVC();
bool decodeKaseikyo();
bool decodeLegoPowerFunctions();
bool decodeLG();
bool decodeMagiQuest(); // not completely standard
bool decodeNEC();
bool decodeRC5();
bool decodeRC6();
bool decodeSamsung();
bool decodeSharp(); // redirected to decodeDenon()
bool decodeSony();
bool decodeWhynter();
bool decodeDistance();
bool decodeHash();
// Template function :-)
bool decodeShuzu();
/*
* Old functions
*/
bool decodeDenonOld(decode_results *aResults);
bool decodeJVCMSB(decode_results *aResults);
bool decodeLGMSB(decode_results *aResults);
bool decodeNECMSB(decode_results *aResults);
bool decodePanasonicMSB(decode_results *aResults);
bool decodeSonyMSB(decode_results *aResults);
bool decodeSAMSUNG(decode_results *aResults);
bool decodeHashOld(decode_results *aResults);
bool decode(
decode_results *aResults)
__attribute__ ((deprecated ("Please use IrReceiver.decode() without a parameter and IrReceiver.decodedIRData.<fieldname> ."))); // deprecated
// for backward compatibility. Now in IRFeedbackLED.hpp
void blink13(uint8_t aEnableLEDFeedback)
__attribute__ ((deprecated ("Please use setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()."))); // deprecated
/*
* Internal functions
*/
void initDecodedIRData();
uint_fast8_t compare(unsigned int oldval, unsigned int newval);
IRData decodedIRData; // New: decoded IR data for the application
// Last decoded IR data for repeat detection
decode_type_t lastDecodedProtocol;
uint32_t lastDecodedAddress;
uint32_t lastDecodedCommand;
uint8_t repeatCount; // Used e.g. for Denon decode for autorepeat decoding.
};
extern uint_fast8_t sBiphaseDecodeRawbuffOffset; //
/*
* Mark & Space matching functions
*/
bool matchTicks(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
bool matchMark(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
bool matchSpace(unsigned int aMeasuredTicks, unsigned int aMatchValueMicros);
/*
* Old function names
*/
bool MATCH(unsigned int measured, unsigned int desired);
bool MATCH_MARK(unsigned int measured_ticks, unsigned int desired_us);
bool MATCH_SPACE(unsigned int measured_ticks, unsigned int desired_us);
int getMarkExcessMicros();
void printActiveIRProtocols(Print *aSerial);
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintGap);
/****************************************************
* Feedback LED related functions
****************************************************/
#define DO_NOT_ENABLE_LED_FEEDBACK 0x00
#define LED_FEEDBACK_DISABLED_COMPLETELY 0x00
#define LED_FEEDBACK_ENABLED_FOR_RECEIVE 0x01
#define LED_FEEDBACK_ENABLED_FOR_SEND 0x02
void setFeedbackLED(bool aSwitchLedOn);
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback); // if aFeedbackLEDPin == 0, then take board BLINKLED_ON() and BLINKLED_OFF() functions
void setLEDFeedback(bool aEnableLEDFeedback); // Direct replacement for blink13()
void enableLEDFeedback();
constexpr auto enableLEDFeedbackForReceive = enableLEDFeedback; // alias for enableLEDFeedback
void disableLEDFeedback();
constexpr auto disableLEDFeedbackForReceive = disableLEDFeedback; // alias for enableLEDFeedback
void enableLEDFeedbackForSend();
void disableLEDFeedbackForSend();
void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please use setLEDFeedback()."))); // deprecated
/*
* Pulse parms are ((X*50)-MARK_EXCESS_MICROS) for the Mark and ((X*50)+MARK_EXCESS_MICROS) for the Space.
* First MARK is the one after the long gap
* Pulse parameters in microseconds
*/
#if !defined(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
#define TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING 25 // Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding.
#endif
/** Lower tolerance for comparison of measured data */
//#define LTOL (1.0 - (TOLERANCE/100.))
#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
/** Upper tolerance for comparison of measured data */
//#define UTOL (1.0 + (TOLERANCE/100.))
#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING)
//#define TICKS_LOW(us) ((int)(((us)*LTOL/MICROS_PER_TICK)))
//#define TICKS_HIGH(us) ((int)(((us)*UTOL/MICROS_PER_TICK + 1)))
#if MICROS_PER_TICK == 50 && TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING == 25 // Defaults
#define TICKS_LOW(us) ((us)/67 ) // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100)
#define TICKS_HIGH(us) (((us)/40) + 1) // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1
#else
#define TICKS_LOW(us) ((unsigned int ) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) ))
#define TICKS_HIGH(us) ((unsigned int ) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1))
#endif
/*
* The receiver instance
*/
extern IRrecv IrReceiver;
/****************************************************
* SENDING
****************************************************/
/**
* Just for better readability of code
*/
#define NO_REPEATS 0
#define SEND_STOP_BIT true
#define SEND_REPEAT_COMMAND true ///< used for e.g. NEC, where a repeat is different from just repeating the data.
/**
* Main class for sending IR signals
*/
class IRsend {
public:
IRsend();
/*
* IR_SEND_PIN is defined
*/
#if defined(IR_SEND_PIN)
void begin();
void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
#else
IRsend(uint_fast8_t aSendPin);
void begin(uint_fast8_t aSendPin);
void setSendPin(uint_fast8_t aSendPin); // required if we use IRsend() as constructor
#endif
// Not guarded for backward compatibility
void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void enableIROut(uint_fast8_t aFrequencyKHz);
void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
unsigned int aZeroSpaceMicros, uint32_t aData, uint_fast8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false);
void sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
void mark(unsigned int aMarkMicros);
void space(unsigned int aSpaceMicros);
void IRLedOff();
// 8 Bit array
void sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
void sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
// 16 Bit array
void sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
void sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
/*
* New send functions
*/
void sendBoseWave(uint8_t aCommand, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendDenon(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendSharp = false);
void sendDenonRaw(uint16_t aRawData, uint_fast8_t aNumberOfRepeats = 0)
#if !defined (DOXYGEN)
__attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
#endif
void sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);
void sendLGRepeat(bool aUseLG2Protocol = false);
void sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false, bool aUseLG2Protocol =
false);
void sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false, bool aUseLG2Protocol = false);
void sendNECRepeat();
void sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
void sendNECRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false);
// NEC variants
void sendOnkyo(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
void sendApple(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
void sendKaseikyo(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats, uint16_t aVendorCode); // LSB first
void sendPanasonic(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
void sendKaseikyo_Denon(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
void sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
void sendRC5(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
void sendRC6(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
void sendSamsungRepeat();
void sendSamsung(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats);
void sendSharp(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats); // redirected to sendDenon
void sendSony(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint8_t numberOfBits = SIRCS_12_PROTOCOL);
void sendLegoPowerFunctions(uint8_t aChannel, uint8_t tCommand, uint8_t aMode, bool aDoSend5Times = true);
void sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times = true);
void sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times = true);
void sendMagiQuest(uint32_t wand_id, uint16_t magnitude);
void sendPronto(const __FlashStringHelper *str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto(const char *prontoHexString, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto(const uint16_t *data, unsigned int length, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
#if defined(__AVR__)
void sendPronto_PF(uint_farptr_t str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
void sendPronto_P(const char *str, uint_fast8_t aNumberOfRepeats);
#endif
// Template protocol :-)
void sendShuzu(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);
/*
* OLD send functions
*/
void sendDenon(unsigned long data, int nbits);
void sendDISH(unsigned long data, int nbits);
void sendJVC(unsigned long data, int nbits,
bool repeat)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendJVC(aAddress, aCommand, aNumberOfRepeats)."))) {
sendJVCMSB(data, nbits, repeat);
}
void sendJVCMSB(unsigned long data, int nbits, bool repeat = false);
void sendLG(unsigned long data, int nbits);
void sendNEC(uint32_t aRawData,
uint8_t nbits)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendNEC(aAddress, aCommand, aNumberOfRepeats)."))) {
sendNECMSB(aRawData, nbits);
}
void sendNECMSB(uint32_t data, uint8_t nbits, bool repeat = false);
void sendPanasonic(uint16_t aAddress,
uint32_t aData)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendPanasonic(aAddress, aCommand, aNumberOfRepeats).")));
void sendRC5(uint32_t data, uint8_t nbits);
void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle);
void sendRC6(uint32_t data, uint8_t nbits);
void sendRC6(uint64_t data, uint8_t nbits);
void sendSharpRaw(unsigned long data, int nbits);
void sendSharp(unsigned int address, unsigned int command);
void sendSAMSUNG(unsigned long data, int nbits);
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung().")));
void sendSony(unsigned long data,
int nbits)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).")));
;
void sendWhynter(unsigned long data, int nbits);
#if !defined(IR_SEND_PIN)
uint8_t sendPin;
#endif
unsigned int periodTimeMicros;
unsigned int periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite.
unsigned int getPulseCorrectionNanos();
void customDelayMicroseconds(unsigned long aMicroseconds);
};
/*
* The sender instance
*/
extern IRsend IrSender;
#endif // _IR_REMOTE_INT_H

View File

@@ -0,0 +1,96 @@
/*
* LongUnion.h
*
* Copyright (C) 2020 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* Arduino-Utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#if !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H)
#include <stdint.h>
#ifndef _WORD_UNION_H
#define _WORD_UNION_H
/**
* Union to specify parts / manifestations of a 16 bit Word without casts and shifts.
* It also supports the compiler generating small code.
*/
union WordUnion {
struct {
uint8_t LowByte;
uint8_t HighByte;
} UByte;
struct {
int8_t LowByte;
int8_t HighByte;
} Byte;
uint8_t UBytes[2];
int8_t Bytes[2];
uint16_t UWord;
int16_t Word;
uint8_t *BytePointer;
};
#endif // _WORD_UNION_H
#ifndef _LONG_UNION_H
#define _LONG_UNION_H
/**
* Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
* It also supports the compiler generating small code.
*/
union LongUnion {
struct {
uint8_t LowByte;
uint8_t MidLowByte;
uint8_t MidHighByte;
uint8_t HighByte;
} UByte;
struct {
int8_t LowByte;
int8_t MidLowByte;
int8_t MidHighByte;
int8_t HighByte;
} Byte;
struct {
uint8_t LowByte;
WordUnion MidWord;
uint8_t HighByte;
} ByteWord;
struct {
int16_t LowWord;
int16_t HighWord;
} Word;
struct {
WordUnion LowWord;
WordUnion HighWord;
} WordUnion;
struct {
uint16_t LowWord;
uint16_t HighWord;
} UWord;
uint8_t UBytes[4]; // seems to have the same code size as using struct UByte
int8_t Bytes[4];
uint16_t UWords[2];
int16_t Words[2];
uint32_t ULong;
int32_t Long;
};
#endif // _LONG_UNION_H
#endif // !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H)

View File

@@ -0,0 +1,114 @@
/*
* TinyIRReceiver.h
*
*
* Copyright (C) 2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* TinyIRReceiver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
#ifndef _TINY_IR_RECEIVER_H
#define _TINY_IR_RECEIVER_H
#include <Arduino.h>
#include "LongUnion.h"
/** \addtogroup TinyReceiver Minimal receiver for NEC protocol
* @{
*/
/*
* This function is called if a complete command was received and must be implemented by the including file (user code)
*/
void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, bool isRepeat);
// LSB first, 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit.
// see: https://www.sbprojects.net/knowledge/ir/nec.php
#define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
#define NEC_COMMAND_BITS 16 // Command and inverted command
#define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
#define NEC_UNIT 560
#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000
#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500
#define NEC_BIT_MARK NEC_UNIT
#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690
#define NEC_ZERO_SPACE NEC_UNIT
#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
#define NEC_REPEAT_PERIOD 110000 // Not used yet - Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
/*
* Macros for comparing timing values
*/
#define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4))
#define upperValue25Percent(aDuration) (aDuration + (aDuration / 4))
#define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2))
#define upperValue50Percent(aDuration) (aDuration + (aDuration / 2))
/*
* The states for the state machine
*/
#define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0
#define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1
#define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4
#define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5
/**
* Control and data variables of the state machine for TinyReceiver
*/
struct TinyIRReceiverStruct {
/*
* State machine
*/
uint32_t LastChangeMicros; ///< microseconds of last Pin Change Interrupt.
uint8_t IRReceiverState; ///< the state of the state machine.
uint8_t IRRawDataBitCounter;
/*
* Data
*/
uint32_t IRRawDataMask;
LongUnion IRRawData;
bool IRRepeatDetected;
};
/*
* Can be used by the callback to transfer received data to main loop for further processing
* E.g. with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
*/
struct TinyIRReceiverCallbackDataStruct {
uint16_t Address;
uint8_t Command;
bool isRepeat;
bool justWritten;
};
void initPCIInterruptForTinyReceiver();
void enablePCIInterruptForTinyReceiver();
void disablePCIInterruptForTinyReceiver();
bool isTinyReceiverIdle();
/** @}*/
#endif // _TINY_IR_RECEIVER_H

View File

@@ -0,0 +1,530 @@
/*
* TinyIRReceiver.hpp
*
* Receives IR protocol data of NEC protocol using pin change interrupts.
* NEC is the protocol of most cheap remote controls for Arduino.
*
* No parity check is done!
* On a completely received IR command, the user function handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition)
* is called in interrupt context but with interrupts being enabled to enable use of delay() etc.
* !!!!!!!!!!!!!!!!!!!!!!
* Functions called in interrupt context should be running as short as possible,
* so if you require longer action, save the data (address + command) and handle them in the main loop.
* !!!!!!!!!!!!!!!!!!!!!
*
*
* Copyright (C) 2021-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/ukw100/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* TinyIRReceiver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* This library can be configured at compile time by the following options / macros:
* For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down)
*
* - IR_INPUT_PIN The pin number for TinyIRReceiver IR input.
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory.
*
*/
#ifndef _TINY_IR_RECEIVER_HPP
#define _TINY_IR_RECEIVER_HPP
#include <Arduino.h>
#include "TinyIRReceiver.h" // If not defined, it defines IR_INPUT_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
#include "digitalWriteFast.h"
/** \addtogroup TinyReceiver Minimal receiver for NEC protocol
* @{
*/
//#define DEBUG // to see if attachInterrupt used
//#define TRACE // to see the state of the ISR state machine
//#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement.
//#define _IR_TIMING_TEST_PIN 7
TinyIRReceiverStruct TinyIRReceiverControl;
/*
* Set input pin and output pin definitions etc.
*/
#if !defined(IR_INPUT_PIN)
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#warning "IR_INPUT_PIN is not defined, so it is set to 10"
#define IR_INPUT_PIN 10
#else
#warning "IR_INPUT_PIN is not defined, so it is set to 2"
#define IR_INPUT_PIN 2
#endif
#endif
#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
#define IR_FEEDBACK_LED_PIN LED_BUILTIN
#endif
#if !( \
(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \
|| defined(__AVR_ATtiny88__) /* MH-ET LIVE Tiny88 */ \
|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
|| defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
|| defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
/* ATmegas with ports 0,1,2 above and ATtiny167 only 2 pins below */ \
|| ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_INPUT_PIN == 3) || (IR_INPUT_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\
|| (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_INPUT_PIN == 3) || (IR_INPUT_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \
)
#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change.
#endif
/**
* Declaration of the callback function provided by the user application.
* It is called every time a complete IR command or repeat was received.
*/
#if defined(ESP32) || defined(ESP8266)
void IRAM_ATTR handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition);
#else
void handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition);
#endif
/**
* The ISR of TinyIRRreceiver.
* It handles the NEC protocol decoding and calls the user callback function on complete.
* 5 us + 3 us for push + pop for a 16MHz ATmega
*/
#if defined(ESP32) || defined(ESP8266)
void IRAM_ATTR IRPinChangeInterruptHandler(void)
#else
void IRPinChangeInterruptHandler(void)
#endif
{
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
/*
* Save IR input level
* Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark.
*/
uint_fast8_t tIRLevel = digitalReadFast(IR_INPUT_PIN);
#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
digitalWriteFast(IR_FEEDBACK_LED_PIN, !tIRLevel);
#endif
/*
* 1. compute microseconds after last change
*/
uint32_t tCurrentMicros = micros();
uint16_t tMicrosOfMarkOrSpace = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros;
TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;
uint8_t tState = TinyIRReceiverControl.IRReceiverState;
#if defined(TRACE)
Serial.print(tState);
Serial.print(' ');
// Serial.print(F(" I="));
// Serial.print(tIRLevel);
// Serial.print(F(" D="));
// Serial.print(tDeltaMicros);
// Serial.println();
#endif
if (tIRLevel == LOW) {
/*
* We have a mark here
*/
if (tMicrosOfMarkOrSpace > 2 * NEC_HEADER_MARK) {
// timeout -> must reset state machine
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) {
// We are at the beginning of the header mark, check timing at the next transition
tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) {
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_SPACE)) {
/*
* We have a valid data header space here -> initialize data
*/
TinyIRReceiverControl.IRRawDataBitCounter = 0;
TinyIRReceiverControl.IRRawData.ULong = 0;
TinyIRReceiverControl.IRRawDataMask = 1;
TinyIRReceiverControl.IRRepeatDetected = false;
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
} else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS) {
/*
* We have a repeat header here and no broken receive before -> set repeat flag
*/
TinyIRReceiverControl.IRRepeatDetected = true;
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
} else {
// This parts are optimized by the compiler into jumps to one code :-)
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
// Check data space length
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(NEC_ZERO_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue50Percent(NEC_ONE_SPACE)) {
// We have a valid bit here
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
if (tMicrosOfMarkOrSpace >= 2 * NEC_UNIT) {
// we received a 1
TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
} else {
// we received a 0 - empty code for documentation
}
// prepare for next bit
TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1;
TinyIRReceiverControl.IRRawDataBitCounter++;
} else {
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
} else {
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else {
/*
* We have a space here
*/
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
/*
* Check length of header mark here
*/
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_MARK)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_MARK)) {
tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK;
} else {
// Wrong length of header mark -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) {
// Check data mark length
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(NEC_BIT_MARK)
&& tMicrosOfMarkOrSpace <= upperValue50Percent(NEC_BIT_MARK)) {
/*
* We have a valid mark here, check for transmission complete
*/
if (TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS || TinyIRReceiverControl.IRRepeatDetected) {
/*
* Code complete -> call callback, no parity check!
*/
// Reset state for new start
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
interrupts(); // enable interrupts, so delay() etc. works in callback
#endif
/*
* Address reduction to 8 bit
*/
if (TinyIRReceiverControl.IRRawData.UByte.LowByte
== (uint8_t) (~TinyIRReceiverControl.IRRawData.UByte.MidLowByte)) {
// standard 8 bit address NEC protocol
TinyIRReceiverControl.IRRawData.UByte.MidLowByte = 0; // Address is the first 8 bit
}
/*
* Call user provided callback here
*/
handleReceivedTinyIRData(TinyIRReceiverControl.IRRawData.UWord.LowWord,
TinyIRReceiverControl.IRRawData.UByte.MidHighByte, TinyIRReceiverControl.IRRepeatDetected);
} else {
// not finished yet
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK;
}
} else {
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
} else {
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
TinyIRReceiverControl.IRReceiverState = tState;
#ifdef _IR_MEASURE_TIMING
digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
#endif
}
bool isTinyReceiverIdle() {
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
}
/**
* Sets IR_INPUT_PIN mode to INPUT_PULLUP, if required, sets feedback LED output mode and call enablePCIInterruptForTinyReceiver()
*/
void initPCIInterruptForTinyReceiver() {
pinModeFast(IR_INPUT_PIN, INPUT_PULLUP);
#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
#endif
enablePCIInterruptForTinyReceiver();
}
#if defined (DEBUG) && !defined(STR)
// Helper macro for getting a macro definition as string
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
/**
* Initializes hardware interrupt generation according to IR_INPUT_PIN or use attachInterrupt() function.
*/
void enablePCIInterruptForTinyReceiver() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
attachInterrupt(IR_INPUT_PIN, IRPinChangeInterruptHandler, CHANGE); // 2.2 us more than version configured with macros and not compatible
#elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
// costs 112 bytes program memory + 4 bytes RAM
attachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN), IRPinChangeInterruptHandler, CHANGE);
# if defined(DEBUG)
Serial.println(F("Use attachInterrupt for pin=" STR(IR_INPUT_PIN)));
# endif
#else
# if defined(DEBUG)
Serial.println(F("Use static interrupt for pin=" STR(IR_INPUT_PIN)));
# endif
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// use PinChangeInterrupt no INT0 for pin PB2
PCMSK = _BV(IR_INPUT_PIN);
// clear interrupt bit
GIFR |= 1 << PCIF;
// enable interrupt on next change
GIMSK |= 1 << PCIE;
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_INPUT_PIN == 3)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IR_INPUT_PIN == 9)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# else
# error "IR_INPUT_PIN must be 9 or 3."
# endif // if (IR_INPUT_PIN == 9)
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_INPUT_PIN == 14)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IR_INPUT_PIN == 3)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# else
# error "IR_INPUT_PIN must be 14 or 3."
# endif // if (IR_INPUT_PIN == 14)
# endif
# else // defined(__AVR_ATtiny25__)
/*
* ATmegas + ATtiny88 here
*/
# if (IR_INPUT_PIN == 2)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IR_INPUT_PIN == 3)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
PCICR |= _BV(PCIE2);
PCMSK2 = digitalPinToBitMask(IR_INPUT_PIN);
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
PCICR |= _BV(PCIE0);
PCMSK0 = digitalPinToBitMask(IR_INPUT_PIN);
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
PCICR |= _BV(PCIE1);
PCMSK1 = digitalPinToBitMask(IR_INPUT_PIN);
# else
# error "IR_INPUT_PIN not allowed."
# endif // if (IR_INPUT_PIN == 2)
# endif // defined(__AVR_ATtiny25__)
#endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
}
void disablePCIInterruptForTinyReceiver() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
detachInterrupt(IR_INPUT_PIN);
#elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
// costs 112 bytes program memory + 4 bytes RAM
detachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN));
#else
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// clear interrupt bit
GIFR |= 1 << PCIF;
// disable interrupt on next change
GIMSK &= ~(1 << PCIE);
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~( 1 << INT0);
# elif (IR_INPUT_PIN == 9)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# else
# error "IR_INPUT_PIN must be 9 or 3."
# endif // if (IR_INPUT_PIN == 9)
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_INPUT_PIN == 14)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~(1 << INT0);
# elif (IR_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# else
# error "IR_INPUT_PIN must be 14 or 3."
# endif // if (IR_INPUT_PIN == 14)
# endif
# else // defined(__AVR_ATtiny25__)
/*
* ATmegas + ATtiny88 here
*/
# if (IR_INPUT_PIN == 2)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~(1 << INT0);
# elif (IR_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
PCICR &= ~(_BV(PCIE2));
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
PCICR &= ~(_BV(PCIE0));
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
//ATmega328 (Uno, Nano ) etc. disable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
PCICR &= ~(_BV(PCIE1));
# else
# error "IR_INPUT_PIN not allowed."
# endif // if (IR_INPUT_PIN == 2)
# endif // defined(__AVR_ATtiny25__)
#endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
}
/*
* Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores.
* The default value of TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT is set in TinyIRReceiver.h
*/
#if defined(__AVR__) && !defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
# if (IR_INPUT_PIN == 2)
ISR(INT0_vect) // Pin 2 global assignment
# elif (IR_INPUT_PIN == 3)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
ISR(INT0_vect) // Pin 3 / PB6 / INT0 is connected to USB+ on DigisparkPro boards
# else
ISR(INT1_vect) // Pin 3 global assignment
# endif
# elif (IR_INPUT_PIN == 9) && defined(ARDUINO_AVR_DIGISPARKPRO) // Digispark pro
ISR(INT1_vect)
# elif (IR_INPUT_PIN == 14) && (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))// For AVR_ATtiny167 INT0 is on pin 14 / PB6
ISR(INT0_vect)
# elif (! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
ISR(PCINT0_vect)
# elif IR_INPUT_PIN == 4 || IR_INPUT_PIN == 5 || IR_INPUT_PIN == 6 || IR_INPUT_PIN == 7
// PCINT for ATmega328 Arduino pins 4 (PD4) to 7 (PD7) - (PCINT 20 to 23)
ISR(PCINT2_vect)
# elif IR_INPUT_PIN == 8 || IR_INPUT_PIN == 9 || IR_INPUT_PIN == 10 || IR_INPUT_PIN == 11 || IR_INPUT_PIN == 12 || IR_INPUT_PIN == 13
// PCINT for ATmega328 Arduino pins 8 (PB0) to 13 (PB5) - (PCINT 0 to 5)
ISR(PCINT0_vect)
# elif IR_INPUT_PIN == A0 || IR_INPUT_PIN == A1 || IR_INPUT_PIN == A2 || IR_INPUT_PIN == A3 || IR_INPUT_PIN == A4 || IR_INPUT_PIN == A5
// PCINT for ATmega328 Arduino pins A1 (PC0) to A5 (PC5) - (PCINT 8 to 13)
ISR(PCINT1_vect)
# endif
{
IRPinChangeInterruptHandler();
}
#endif // defined(__AVR__) && ! defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
/** @}*/
#endif // _TINY_IR_RECEIVER_HPP

View File

@@ -0,0 +1,138 @@
/*
* ac_LG.h
*
* Contains definitions for receiving and sending LG air conditioner IR Protocol
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2021 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.
*
************************************************************************************
*/
// see also: https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h
#ifndef _AC_LG_H
#define _AC_LG_H
#include <Arduino.h>
/** \addtogroup Airconditoners Air conditioner special code
* @{
*/
#define LG_ADDRESS 0x88
/*
* The basic IR command codes
* Parts of the codes (especially the lower nibbles) may be modified to contain
* additional information like temperature, fan speed and minutes.
*/
#define LG_SWITCH_ON_MASK 0x0800 // This bit is masked if we switch Power on
#define LG_MODE_COOLING 0x0800 // Temperature and fan speed in lower nibbles
#define LG_MODE_DEHUMIDIFIYING 0x0990 // sets also temperature to 24 and fan speed to 0
#define LG_MODE_FAN 0x0A30 // sets also temperature to 18
#define LG_MODE_AUTO 0x0B00 // The remote initially sets also temperature to 22 and fan speed to 4
#define LG_MODE_HEATING 0x0C00 // Temperature and fan speed in lower nibbles
#define LG_ENERGY_SAVING_ON 0x1004
#define LG_ENERGY_SAVING_OFF 0x1005
#define LG_JET_ON 0x1008
#define LG_WALL_SWING_ON 0x1314
#define LG_WALL_SWING_OFF 0x1315
#define LG_SWING_ON 0x1316 // not verified, for AKB73757604
#define LG_SWING_OFF 0x1317 // not verified, for AKB73757604
#define LG_TIMER_ON 0x8000 // relative minutes in lower nibbles
#define LG_TIMER_OFF 0x9000 // relative minutes in lower nibbles
#define LG_SLEEP 0xA000 // relative minutes in lower nibbles
#define LG_CLEAR_ALL 0xB000 // Timers and sleep
#define LG_POWER_DOWN 0xC005
#define LG_LIGHT 0xC00A
#define LG_AUTO_CLEAN_ON 0xC00B
#define LG_AUTO_CLEAN_OFF 0xC00C
/*
* Commands as printed in menu and uses as first parameter for sendCommandAndParameter
*/
#define LG_COMMAND_OFF '0'
#define LG_COMMAND_ON '1'
#define LG_COMMAND_SWING 's'
#define LG_COMMAND_AUTO_CLEAN 'a'
#define LG_COMMAND_JET 'j'
#define LG_COMMAND_ENERGY 'e'
#define LG_COMMAND_LIGHT 'l'
#define LG_COMMAND_FAN_SPEED 'f'
#define LG_COMMAND_TEMPERATURE 't'
#define LG_COMMAND_TEMPERATURE_PLUS '+'
#define LG_COMMAND_TEMPERATURE_MINUS '-'
#define LG_COMMAND_MODE 'm'
#define LG_COMMAND_SLEEP 'S'
#define LG_COMMAND_TIMER_ON 'T'
#define LG_COMMAND_TIMER_OFF 'O'
#define LG_COMMAND_CLEAR_ALL 'C'
/*
* The modes are encoded as character values for easy printing :-)
*/
#define AC_MODE_COOLING 'c'
#define AC_MODE_DEHUMIDIFIYING 'd'
#define AC_MODE_FAN 'f'
#define AC_MODE_AUTO 'a'
#define AC_MODE_HEATING 'h'
// see https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/ir_LG.h
union LGProtocol {
uint32_t raw; ///< The state of the IR remote in IR code form.
struct {
uint32_t Checksum :4;
uint32_t Fan :3;
uint32_t FanExt :1;
uint32_t Temp :4;
uint32_t Mode :4; // highest bit 1 => Set temperature and ventilation by mode
uint32_t Function :3;
uint32_t SwitchOnMask :1; /* Content is 0 when switching from off to on */
uint32_t Signature :8; /* Content is 0x88, LG_ADDRESS */
};
};
class Aircondition_LG {
public:
bool sendCommandAndParameter(char aCommand, int aParameter);
void setType(bool aIsWallType);
void printMenu(Print *aSerial);
void sendIRCommand(uint16_t aCommand);
void sendTemperatureFanSpeedAndMode();
/*
* Internal state of the air condition
*/
#define LG_IS_WALL_TYPE true
#define LG_IS_TOWER_TYPE false
bool ACIsWallType; // false : TOWER, true : WALL
bool PowerIsOn;
// These value are encoded and sent by AC_LG_SendCommandAndParameter()
uint8_t FanIntensity = 1; // 0 -> low, 4 high, 5 -> cycle
uint8_t Temperature = 22; // temperature : 18 ~ 30
uint8_t Mode = AC_MODE_COOLING;
bool useLG2Protocol = false;
};
/** @}*/
#endif // _AC_LG_H

View File

@@ -0,0 +1,322 @@
/*
* ac_LG.hpp
*
* Contains functions for sending LG air conditioner IR Protocol
* There is no state plausibility check, e.g. you can send fan speed in Mode D and change temperature in mode F
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2021-2022 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _AC_LG_HPP
#define _AC_LG_HPP
#include <Arduino.h>
#if defined(INFO) && !defined(LOCAL_INFO)
#define LOCAL_INFO
#else
//#define LOCAL_INFO // This enables info output only for this file
#endif
//#define DEBUG // for more output from the LG-AC driver.
#include "IRremoteInt.h"
#include "ac_LG.h" // useful constants
#include "LongUnion.h"
/** \addtogroup Airconditoners Air conditioner special code
* @{
*/
/*
* LG remote measurements: Type AKB73315611, Ver1.1 from 2011.03.01
* Internal crystal: 4 MHz
* Header: 8.9 ms mark 4.15 ms space
* Data: 500 / 540 and 500 / 1580;
* Clock is nor synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark
* Duty: 9 us on 17 us off => around 33 % duty
* NO REPEAT: If value like temperature has changed during long press, the last value is send at button release
* If you do a double press -tested with the fan button-, the next value can be sent after 118 ms
*/
#define SIZE_OF_FAN_SPEED_MAPPING_TABLE 4
const int AC_FAN_TOWER[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 4, 6, 6 }; // last dummy entry to avoid out of bounds access
const int AC_FAN_WALL[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 2, 4, 5 }; // 0 -> low, 4 high, 5 -> cycle
void Aircondition_LG::setType(bool aIsWallType) {
ACIsWallType = aIsWallType;
#if defined(LOCAL_INFO)
Serial.print(F("Set wall type to "));
Serial.println(aIsWallType);
#endif
}
void Aircondition_LG::printMenu(Print *aSerial) {
aSerial->println();
aSerial->println();
aSerial->println(F("Type command and optional parameter without a separator"));
aSerial->println(F("0 Off"));
aSerial->println(F("1 On"));
aSerial->println(F("s Swing <0 or 1>"));
aSerial->println(F("a Auto clean <0 or 1>"));
aSerial->println(F("j Jet on"));
aSerial->println(F("e Energy saving <0 or 1>"));
aSerial->println(F("l Lights toggle"));
aSerial->println(F("f Fan speed <0 to 2 or 3 for cycle>"));
aSerial->println(F("t Temperature <18 to 30> degree"));
aSerial->println(F("+ Temperature + 1"));
aSerial->println(F("- Temperature - 1"));
aSerial->println(F("m <c(ool) or a(uto) or d(ehumidifying) or h(eating) or f(an) mode>"));
aSerial->println(F("S Sleep after <0 to 420> minutes"));
aSerial->println(F("T Timer on after <0 to 1439> minutes"));
aSerial->println(F("O Timer off after <0 to 1439> minutes"));
aSerial->println(F("C Clear all timer and sleep"));
aSerial->println(F("e.g. \"s1\" or \"t23\" or \"mc\" or \"O60\" or \"+\""));
aSerial->println(F("No plausibility check is made!"));
aSerial->println();
}
/*
* Send repeat
* Repeat commands should be sent in a 110 ms raster.
* @param aCommand one of LG_COMMAND_OFF, LG_COMMAND_ON etc.
*/
bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) {
// Commands without parameter
switch (aCommand) {
case LG_COMMAND_OFF: // off
sendIRCommand(LG_POWER_DOWN);
PowerIsOn = false;
return true;
case LG_COMMAND_ON: // on
PowerIsOn = false; // set to false in order to suppress on bit
sendTemperatureFanSpeedAndMode();
return true;
case LG_COMMAND_JET:
IR_DEBUG_PRINTLN(F("Send jet on"));
sendIRCommand(LG_JET_ON);
return true;
case LG_COMMAND_LIGHT:
sendIRCommand(LG_LIGHT);
return true;
case LG_COMMAND_CLEAR_ALL:
sendIRCommand(LG_CLEAR_ALL);
return true;
case LG_COMMAND_TEMPERATURE_PLUS:
if (18 <= Temperature && Temperature <= 29) {
Temperature++;
sendTemperatureFanSpeedAndMode();
} else {
return false;
}
return true;
case LG_COMMAND_TEMPERATURE_MINUS:
if (19 <= Temperature && Temperature <= 30) {
Temperature--;
sendTemperatureFanSpeedAndMode();
} else {
return false;
}
return true;
}
PowerIsOn = true;
/*
* Now the commands which require a parameter
*/
if (aParameter < 0) {
IR_DEBUG_PRINT(F("Error: Parameter is less than 0"));
return false;
}
switch (aCommand) {
case LG_COMMAND_MODE:
Mode = aParameter + '0';
sendTemperatureFanSpeedAndMode();
break;
case LG_COMMAND_SWING:
IR_DEBUG_PRINT(F("Send air swing="));
IR_DEBUG_PRINTLN(aParameter);
if (ACIsWallType) {
if (aParameter) {
sendIRCommand(LG_WALL_SWING_ON);
} else {
sendIRCommand(LG_WALL_SWING_OFF);
}
} else {
if (aParameter) {
sendIRCommand(LG_SWING_ON);
} else {
sendIRCommand(LG_SWING_OFF);
}
}
break;
case LG_COMMAND_AUTO_CLEAN:
IR_DEBUG_PRINT(F("Send auto clean="));
IR_DEBUG_PRINTLN(aParameter);
if (aParameter) {
sendIRCommand(LG_AUTO_CLEAN_ON);
} else {
sendIRCommand(LG_AUTO_CLEAN_OFF);
}
break;
case LG_COMMAND_ENERGY:
IR_DEBUG_PRINT(F("Send energy saving on="));
IR_DEBUG_PRINTLN(aParameter);
if (aParameter) {
sendIRCommand(LG_ENERGY_SAVING_ON);
} else {
sendIRCommand(LG_ENERGY_SAVING_OFF);
}
break;
case LG_COMMAND_FAN_SPEED:
if (aParameter < SIZE_OF_FAN_SPEED_MAPPING_TABLE) {
FanIntensity = aParameter;
sendTemperatureFanSpeedAndMode();
} else {
return false;
}
break;
case LG_COMMAND_TEMPERATURE:
if (18 <= aParameter && aParameter <= 30) {
Temperature = aParameter;
sendTemperatureFanSpeedAndMode();
} else {
return false;
}
break;
case LG_COMMAND_SLEEP:
// 420 = maximum I have recorded
if (aParameter <= 420) {
sendIRCommand(LG_SLEEP + aParameter);
} else {
return false;
}
break;
case LG_COMMAND_TIMER_ON:
// 1440 = minutes of a day
if (aParameter <= 1439) {
sendIRCommand(LG_TIMER_ON + aParameter);
} else {
return false;
}
break;
case LG_COMMAND_TIMER_OFF:
if (aParameter <= 1439) {
sendIRCommand(LG_TIMER_OFF + aParameter);
} else {
return false;
}
break;
default:
return false;
}
return true;
}
void Aircondition_LG::sendIRCommand(uint16_t aCommand) {
#if defined(LOCAL_INFO)
Serial.print(F("Send code=0x"));
Serial.print(aCommand, HEX);
Serial.print(F(" | 0b"));
Serial.println(aCommand, BIN);
#endif
IrSender.sendLG((uint8_t) LG_ADDRESS, aCommand, 0, false, useLG2Protocol);
}
/*
* Takes values from static variables
*/
void Aircondition_LG::sendTemperatureFanSpeedAndMode() {
uint8_t tTemperature = Temperature;
#if defined(LOCAL_INFO)
Serial.print(F("Send temperature="));
Serial.print(tTemperature);
Serial.print(F(" fan intensity="));
Serial.print(FanIntensity);
Serial.print(F(" mode="));
Serial.println((char )Mode);
#endif
WordUnion tIRCommand;
tIRCommand.UWord = 0;
// Temperature is coded in the upper nibble of the LowByte
tIRCommand.UByte.LowByte = ((tTemperature - 15) << 4); // 16 -> 0x00, 18 -> 0x30, 30 -> 0xF0
// Fan intensity is coded in the lower nibble of the LowByte
if (ACIsWallType) {
tIRCommand.UByte.LowByte |= AC_FAN_WALL[FanIntensity];
} else {
tIRCommand.UByte.LowByte |= AC_FAN_TOWER[FanIntensity];
}
switch (Mode) {
case AC_MODE_COOLING:
tIRCommand.UByte.HighByte = LG_MODE_COOLING >> 8;
break;
case AC_MODE_HEATING:
tIRCommand.UByte.HighByte = LG_MODE_HEATING >> 8;
break;
case AC_MODE_AUTO:
tIRCommand.UByte.HighByte = LG_MODE_AUTO >> 8;
break;
case AC_MODE_FAN:
tTemperature = 18;
tIRCommand.UByte.HighByte = LG_MODE_FAN >> 8;
break;
case AC_MODE_DEHUMIDIFIYING:
tIRCommand.UWord = LG_MODE_DEHUMIDIFIYING;
break;
default:
break;
}
if (!PowerIsOn) {
// switch on requires masked bit
tIRCommand.UByte.HighByte &= ~(LG_SWITCH_ON_MASK >> 8);
}
PowerIsOn = true;
sendIRCommand(tIRCommand.UWord);
}
/** @}*/
#endif // _AC_LG_HPP

View File

@@ -0,0 +1,492 @@
/*
Optimized digital functions for AVR microcontrollers
by Watterott electronic (www.watterott.com)
based on http://code.google.com/p/digitalwritefast
*/
#ifndef __digitalWriteFast_h_
#define __digitalWriteFast_h_ 1
//#define SANGUINO_PINOUT //define for Sanguino pinout
// general macros/defines
#if !defined(BIT_READ)
# define BIT_READ(value, bit) ((value) & (1UL << (bit)))
#endif
#if !defined(BIT_SET)
# define BIT_SET(value, bit) ((value) |= (1UL << (bit)))
#endif
#if !defined(BIT_CLEAR)
# define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit)))
#endif
#if !defined(BIT_WRITE)
# define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit))
#endif
#if !defined(SWAP)
# define SWAP(x,y) do{ (x)=(x)^(y); (y)=(x)^(y); (x)=(x)^(y); }while(0)
#endif
#if !defined(DEC)
# define DEC (10)
#endif
#if !defined(HEX)
# define HEX (16)
#endif
#if !defined(OCT)
# define OCT (8)
#endif
#if !defined(BIN)
# define BIN (2)
#endif
// workarounds for ARM microcontrollers
#if (!defined(__AVR__) || \
defined(ARDUINO_ARCH_SAM) || \
defined(ARDUINO_ARCH_SAMD))
#if !defined(PROGMEM)
# define PROGMEM
#endif
#if !defined(PGM_P)
# define PGM_P const char *
#endif
#if !defined(PSTR)
# define PSTR(str) (str)
#endif
#if !defined(memcpy_P)
# define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
#endif
#if !defined(strcpy_P)
# define strcpy_P(dst, src) strcpy((dst), (src))
#endif
#if !defined(strcat_P)
# define strcat_P(dst, src) strcat((dst), (src))
#endif
#if !defined(strcmp_P)
# define strcmp_P(a, b) strcmp((a), (b))
#endif
#if !defined(strcasecmp_P)
# define strcasecmp_P(a, b) strcasecmp((a), (b))
#endif
#if !defined(strncmp_P)
# define strncmp_P(a, b, n) strncmp((a), (b), (n))
#endif
#if !defined(strncasecmp_P)
# define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n))
#endif
#if !defined(strstr_P)
# define strstr_P(a, b) strstr((a), (b))
#endif
#if !defined(strlen_P)
# define strlen_P(a) strlen((a))
#endif
#if !defined(sprintf_P)
# define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
#endif
#if !defined(pgm_read_byte)
# define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#endif
#if !defined(pgm_read_word)
# define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
#if !defined(pgm_read_dword)
# define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#endif
#endif
// digital functions
//#if !defined(digitalPinToPortReg)
#define SPI_SW_SS_PIN (10) //SS on Uno (for software SPI)
#define SPI_SW_MOSI_PIN (11) //MOSI on Uno (for software SPI)
#define SPI_SW_MISO_PIN (12) //MISO on Uno (for software SPI)
#define SPI_SW_SCK_PIN (13) //SCK on Uno (for software SPI)
// --- Arduino Due and SAM3X8E based boards ---
#if (defined(ARDUINO_SAM_DUE) || \
defined(__SAM3X8E__))
#define UART_RX_PIN (0)
#define UART_TX_PIN (1)
#define I2C_SDA_PIN (20)
#define I2C_SCL_PIN (21)
#define SPI_HW_SS_PIN (78) //SS0:77, SS1:87, SS2:86, SS3:78
#define SPI_HW_MOSI_PIN (75) //75
#define SPI_HW_MISO_PIN (74) //74
#define SPI_HW_SCK_PIN (76) //76
// --- Arduino Zero and SAMD21G18 based boards ---
#elif (defined(ARDUINO_SAMD_ZERO) || \
defined(__SAMD21G18A__))
#define UART_RX_PIN (0)
#define UART_TX_PIN (1)
#define I2C_SDA_PIN (16)
#define I2C_SCL_PIN (17)
#define SPI_HW_SS_PIN (14) //14
#define SPI_HW_MOSI_PIN (21) //21
#define SPI_HW_MISO_PIN (18) //18
#define SPI_HW_SCK_PIN (20) //20
// --- Arduino Mega and ATmega128x/256x based boards ---
#elif (defined(ARDUINO_AVR_MEGA) || \
defined(ARDUINO_AVR_MEGA1280) || \
defined(ARDUINO_AVR_MEGA2560) || \
defined(__AVR_ATmega1280__) || \
defined(__AVR_ATmega1281__) || \
defined(__AVR_ATmega2560__) || \
defined(__AVR_ATmega2561__))
#define UART_RX_PIN (0) //PE0
#define UART_TX_PIN (1) //PE1
#define I2C_SDA_PIN (20)
#define I2C_SCL_PIN (21)
#define SPI_HW_SS_PIN (53) //PB0
#define SPI_HW_MOSI_PIN (51) //PB2
#define SPI_HW_MISO_PIN (50) //PB3
#define SPI_HW_SCK_PIN (52) //PB1
#define __digitalPinToPortReg(P) \
(((P) >= 22 && (P) <= 29) ? &PORTA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \
(((P) >= 30 && (P) <= 37) ? &PORTC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \
((((P) <= 3) || (P) == 5) ? &PORTE : \
(((P) >= 54 && (P) <= 61) ? &PORTF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \
(((P) == 14 || (P) == 15) ? &PORTJ : \
(((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL))))))))))
#define __digitalPinToDDRReg(P) \
(((P) >= 22 && (P) <= 29) ? &DDRA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \
(((P) >= 30 && (P) <= 37) ? &DDRC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \
((((P) <= 3) || (P) == 5) ? &DDRE : \
(((P) >= 54 && (P) <= 61) ? &DDRF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \
(((P) == 14 || (P) == 15) ? &DDRJ : \
(((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL))))))))))
#define __digitalPinToPINReg(P) \
(((P) >= 22 && (P) <= 29) ? &PINA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \
(((P) >= 30 && (P) <= 37) ? &PINC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \
((((P) <= 3) || (P) == 5) ? &PINE : \
(((P) >= 54 && (P) <= 61) ? &PINF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \
(((P) == 14 || (P) == 15) ? &PINJ : \
(((P) >= 62 && (P) <= 69) ? &PINK : &PINL))))))))))
#define __digitalPinToBit(P) \
(((P) >= 7 && (P) <= 9) ? (P) - 3 : \
(((P) >= 10 && (P) <= 13) ? (P) - 6 : \
(((P) >= 22 && (P) <= 29) ? (P) - 22 : \
(((P) >= 30 && (P) <= 37) ? 37 - (P) : \
(((P) >= 39 && (P) <= 41) ? 41 - (P) : \
(((P) >= 42 && (P) <= 49) ? 49 - (P) : \
(((P) >= 50 && (P) <= 53) ? 53 - (P) : \
(((P) >= 54 && (P) <= 61) ? (P) - 54 : \
(((P) >= 62 && (P) <= 69) ? (P) - 62 : \
(((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \
(((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \
(((P) == 19) ? 2 : \
(((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \
(((P) == 2) ? 4 : \
(((P) == 3 || (P) == 4) ? 5 : 7)))))))))))))))
// --- Arduino MightyCore standard pinout ---
#elif (defined(__AVR_ATmega1284P__) || \
defined(__AVR_ATmega1284__) || \
defined(__AVR_ATmega644P__) || \
defined(__AVR_ATmega644A__) || \
defined(__AVR_ATmega644__) || \
defined(__AVR_ATmega324PB__) || \
defined(__AVR_ATmega324PA__) || \
defined(__AVR_ATmega324P__) || \
defined(__AVR_ATmega324A__) || \
defined(__AVR_ATmega164P__) || \
defined(__AVR_ATmega164A__) || \
defined(__AVR_ATmega32__) || \
defined(__AVR_ATmega16__) || \
defined(__AVR_ATmega8535__)) && \
!defined(BOBUINO_PINOUT)
#define UART_RX_PIN (8) //PD0
#define UART_TX_PIN (9) //PD1
#define I2C_SDA_PIN (17) //PC1
#define I2C_SCL_PIN (16) //PC0
#define SPI_HW_SS_PIN (4) //PB4
#define SPI_HW_MOSI_PIN (5) //PB5
#define SPI_HW_MISO_PIN (6) //PB6
#define SPI_HW_SCK_PIN (7) //PB7
#if defined(__AVR_ATmega324PB__)
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE))))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE))))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE))))
# if defined(SANGUINO_PINOUT)
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (7 - ((P) - 24)) : (P) - 32))))
# else //MightyCore Pinout
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (P) - 24 : (P) - 32))))
# endif
#else
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA)))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : &DDRA)))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : &PINA)))
# if defined(SANGUINO_PINOUT)
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24)))))
# else //MightyCore Pinout
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24)))
# endif
#endif
// --- Arduino Leonardo and ATmega16U4/32U4 based boards ---
#elif (defined(ARDUINO_AVR_LEONARDO) || \
defined(__AVR_ATmega16U4__) || \
defined(__AVR_ATmega32U4__))
#define UART_RX_PIN (0) //PD2
#define UART_TX_PIN (1) //PD3
#define I2C_SDA_PIN (2) //PD1
#define I2C_SCL_PIN (3) //PD0
#define SPI_HW_SS_PIN (17) //PB0
#define SPI_HW_MOSI_PIN (16) //PB2
#define SPI_HW_MISO_PIN (14) //PB3
#define SPI_HW_SCK_PIN (15) //PB1
#define __digitalPinToPortReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PORTD : (((P) == 5 || (P) == 13) ? &PORTC : (((P) >= 18 && (P) <= 23)) ? &PORTF : (((P) == 7) ? &PORTE : &PORTB)))
#define __digitalPinToDDRReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &DDRD : (((P) == 5 || (P) == 13) ? &DDRC : (((P) >= 18 && (P) <= 23)) ? &DDRF : (((P) == 7) ? &DDRE : &DDRB)))
#define __digitalPinToPINReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PIND : (((P) == 5 || (P) == 13) ? &PINC : (((P) >= 18 && (P) <= 23)) ? &PINF : (((P) == 7) ? &PINE : &PINB)))
#define __digitalPinToBit(P) \
(((P) >= 8 && (P) <= 11) ? (P) - 4 : (((P) >= 18 && (P) <= 21) ? 25 - (P) : (((P) == 0) ? 2 : (((P) == 1) ? 3 : (((P) == 2) ? 1 : (((P) == 3) ? 0 : (((P) == 4) ? 4 : (((P) == 6) ? 7 : (((P) == 13) ? 7 : (((P) == 14) ? 3 : (((P) == 15) ? 1 : (((P) == 16) ? 2 : (((P) == 17) ? 0 : (((P) == 22) ? 1 : (((P) == 23) ? 0 : (((P) == 24) ? 4 : (((P) == 25) ? 7 : (((P) == 26) ? 4 : (((P) == 27) ? 5 : 6 )))))))))))))))))))
// --- Arduino Uno and ATmega168/328 based boards ---
#elif (defined(ARDUINO_AVR_UNO) || \
defined(ARDUINO_AVR_DUEMILANOVE) || \
defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48__) || \
defined(__AVR_ATmega48P__) || \
defined(__AVR_ATmega48PB__) || \
defined(__AVR_ATmega88P__) || \
defined(__AVR_ATmega88PB__) || \
defined(__AVR_ATmega168__) || \
defined(__AVR_ATmega168PA__) || \
defined(__AVR_ATmega168PB__) || \
defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega328PB__))
#define UART_RX_PIN (0) //PD0
#define UART_TX_PIN (1) //PD1
#define I2C_SDA_PIN (18) //A4
#define I2C_SCL_PIN (19) //A5
#define SPI_HW_SS_PIN (10) //PB0
#define SPI_HW_MOSI_PIN (11) //PB2
#define SPI_HW_MISO_PIN (12) //PB3
#define SPI_HW_SCK_PIN (13) //PB1
#if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__)
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE)))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : (((P) >= 14 && (P) <= 19) ? &DDRC : &DDRE)))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : (((P) >= 14 && (P) <= 19) ? &PINC : &PINE)))
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (((P) >= 14 && (P) <= 19) ? (P) - 14 : (((P) >= 20 && (P) <= 21) ? (P) - 18 : (P) - 22))))
#else
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC))
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
#endif
// --- Arduino Uno WiFi Rev 2, Nano Every ---
#elif defined(__AVR_ATmega4809__)
#define UART_RX_PIN (0) //PB0
#define UART_TX_PIN (1) //PB1
#define I2C_SDA_PIN (22) //PA2
#define I2C_SCL_PIN (23) //PA3
#define SPI_HW_SS_PIN (8) //PE3
#define SPI_HW_MOSI_PIN (11) //PE0
#define SPI_HW_MISO_PIN (12) //PE1
#define SPI_HW_SCK_PIN (13) //PE2
#define __digitalPinToPortReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT)
#define __digitalPinToDDRReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR)
#define __digitalPinToPINReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN)
#define __digitalPinToBit(P) \
(((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 )
// TinyCore
// https://raw.githubusercontent.com/xukangmin/TinyCore/master/avr/package/package_tinycore_index.json
// https://docs.tinycore.dev/en/latest/
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define __digitalPinToPortReg(P) ((P) <= 5 ? &VPORTB.OUT : ((P) <= 9 ? &VPORTC.OUT : ((P) <= 16 ? &VPORTA.OUT : ((P) <= 18 ? &VPORTB.OUT : &VPORTC.OUT))))
#define __digitalPinToDDRReg(P) ((P) <= 5 ? &VPORTB.DIR : ((P) <= 9 ? &VPORTC.DIR : ((P) <= 16 ? &VPORTA.DIR : ((P) <= 18 ? &VPORTB.DIR : &VPORTC.DIR))))
#define __digitalPinToPINReg(P) ((P) <= 5 ? &VPORTB.IN : ((P) <= 9 ? &VPORTC.IN : ((P) <= 16 ? &VPORTA.IN : ((P) <= 18 ? &VPORTB.IN : &VPORTC.IN))))
#define __digitalPinToBit(P) ( (P) <= 3 ? (3 - P) : ((P) <= 5 ? (P) : ((P) <= 9 ? (P - 6) : ((P) <= 16 ? ((P) - 9) : ((P) <= 18 ? ((P) - 11) : ((P) - 15))))) )
// --- ATtinyX5 ---
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// we have only PORTB
#define __digitalPinToPortReg(P) (&PORTB)
#define __digitalPinToDDRReg(P) (&DDRB)
#define __digitalPinToPINReg(P) (&PINB)
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
// --- ATtiny88 ---
#elif defined(__AVR_ATtiny88__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC)))
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC)))
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC)))
#define __digitalPinToBit(P) ( (P) <= 7 ? (P) : ((P) <= 13 ? ((P) - 8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P) - 14) : ((P) <= 18 ? ((P) - 17) : ((P) == 25 ? 7 : ((P) - 19)))))) )
# else
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC))))
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC))))
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC))))
#define __digitalPinToBit(P) ((P) <= 15 ? ((P) & 0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P) - 17) : ((P) == 27 ? (6) : ((P) - 23)))))
# endif
// --- ATtinyX4 + ATtinyX7 ---
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO) || PIN_PA7 == 5
// Strange enumeration of pins on Digispark board and core library
#define __digitalPinToPortReg(P) (((P) <= 4) ? &PORTB : &PORTA)
#define __digitalPinToDDRReg(P) (((P) <= 4) ? &DDRB : &DDRA)
#define __digitalPinToPINReg(P) (((P) <= 4) ? &PINB : &PINA)
#define __digitalPinToBit(P) (((P) <= 2) ? (P) : (((P) == 3) ? 6 : (((P) == 4) ? 3 : (((P) == 5) ? 7 : (P) - 6 ))))
# else
// ATtinyX4: PORTA for 0 to 7, PORTB for 8 to 11
// ATtinyX7: PORTA for 0 to 7, PORTB for 8 to 15
#define __digitalPinToPortReg(P) (((P) <= 7) ? &PORTA : &PORTB)
#define __digitalPinToDDRReg(P) (((P) <= 7) ? &DDRA : &DDRB)
#define __digitalPinToPINReg(P) (((P) <= 7) ? &PINA : &PINB)
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 )
# endif
// --- Other ---
#else
#define I2C_SDA_PIN SDA
#define I2C_SCL_PIN SCL
#define SPI_HW_SS_PIN SS
#define SPI_HW_MOSI_PIN MOSI
#define SPI_HW_MISO_PIN MISO
#define SPI_HW_SCK_PIN SCK
#endif
//#endif //#if !defined(digitalPinToPortReg)
#if !defined(digitalWriteFast)
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
#define digitalWriteFast(P, V) \
if (__builtin_constant_p(P)) { \
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
} else { \
digitalWrite((P), (V)); \
}
#else
#define digitalWriteFast digitalWrite
#endif
#endif
#if !defined(pinModeFast)
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
#define pinModeFast(P, V) \
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
if (V == INPUT_PULLUP) {\
BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
} else { \
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
} \
} else { \
pinMode((P), (V)); \
}
#else
#define pinModeFast pinMode
#endif
#endif // !defined(pinModeFast)
#if !defined(digitalReadFast)
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
#define __digitalReadFast(P ) \
(__builtin_constant_p(P) ) ? \
(( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
digitalRead((P))
#else
#define digitalReadFast digitalRead
#endif
#endif // !defined(digitalReadFast)
#if !defined(digitalToggleFast)
#if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR))
#define digitalToggleFast(P) \
if (__builtin_constant_p(P)) { \
BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
} else { \
digitalWrite(P, ! digitalRead(P)); \
}
#else
#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P))
#endif
#endif // !defined(digitalToggleFast)
#endif //__digitalWriteFast_h_

View File

@@ -0,0 +1,137 @@
/*
* ir_BoseWave.cpp
*
* Contains functions for receiving and sending Bose IR Protocol
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
*/
#ifndef _IR_BOSEWAVE_HPP
#define _IR_BOSEWAVE_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// BBBB OOO SSSS EEEEE
// B B O O S E
// BB B O O SSS EEEE
// B B O O S E
// BBBB OOO SSSS EEEEE
//==============================================================================
// see http://lirc.sourceforge.net/remotes/bose/WAVERADIO
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#BOSE
//
// Support for Bose Wave Radio CD initially provided by https://github.com/uvotguy.
//
// As seen on my trusty oscilloscope, there is no repeat code. Instead, when I
// press and hold a button on my remote, it sends a command, makes a 51.2ms space,
// and resends the command, etc, etc.
// LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit.
#define BOSEWAVE_BITS 16 // Command and inverted command
#define BOSEWAVE_HEADER_MARK 1014 // 1014 are 39 clock periods (I counted 3 times!)
#define BOSEWAVE_HEADER_SPACE 1468 // 1468(measured), 1456 are 56 clock periods
#define BOSEWAVE_BIT_MARK 520 // 520 are 20 clock periods
#define BOSEWAVE_ZERO_SPACE 468 // 468 are 18 clock periods
#define BOSEWAVE_ONE_SPACE 1468 // 1468(measured), 1456 are 56 clock periods
#define BOSEWAVE_REPEAT_SPACE 50000
//+=============================================================================
void IRsend::sendBoseWave(uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(BOSEWAVE_KHZ); // 38 kHz
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Header
mark(BOSEWAVE_HEADER_MARK);
space(BOSEWAVE_HEADER_SPACE);
// send 8 command bits and then 8 inverted command bits LSB first
uint16_t tData = ((~aCommand) << 8) | aCommand;
sendPulseDistanceWidthData(BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, tData,
BOSEWAVE_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command with a fixed space gap
delay( BOSEWAVE_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
bool IRrecv::decodeBoseWave() {
// Check header "mark"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], BOSEWAVE_HEADER_MARK)) {
// no debug output, since this check is mainly to determine the received protocol
return false;
}
// Check we have enough data +4 for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * BOSEWAVE_BITS) + 4) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}
// Check header "space"
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], BOSEWAVE_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
if (!decodePulseDistanceData(BOSEWAVE_BITS, 3, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_ZERO_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * BOSEWAVE_BITS)], BOSEWAVE_BIT_MARK)) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
uint16_t tDecodedValue = decodedIRData.decodedRawData;
uint8_t tCommandNotInverted = tDecodedValue & 0xFF; // comes first and is in the lower bits (LSB first :-))
uint8_t tCommandInverted = tDecodedValue >> 8;
// parity check for command. Use this variant to avoid compiler warning "comparison of promoted ~unsigned with unsigned [-Wsign-compare]"
if ((tCommandNotInverted ^ tCommandInverted) != 0xFF) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINT(F("Command and inverted command check failed"));
return false;
}
// check for repeat
if (decodedIRData.rawDataPtr->rawbuf[0] < ((BOSEWAVE_REPEAT_SPACE + (BOSEWAVE_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
}
decodedIRData.command = tCommandNotInverted;
decodedIRData.protocol = BOSEWAVE;
decodedIRData.numberOfBits = BOSEWAVE_BITS;
return true;
}
/** @}*/
#endif // _IR_BOSEWAVE_HPP

View File

@@ -0,0 +1,253 @@
/*
* ir_Denon.cpp
*
* Contains functions for receiving and sending Denon/Sharp IR Protocol
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_DENON_HPP
#define _IR_DENON_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// DDDD EEEEE N N OOO N N
// D D E NN N O O NN N
// D D EEE N N N O O N N N
// D D E N NN O O N NN
// DDDD EEEEE N N OOO N N
//==============================================================================
// SSSS H H AAA RRRR PPPP
// S H H A A R R P P
// SSS HHHHH AAAAA RRRR PPPP
// S H H A A R R P
// SSSS H H A A R R P
//==============================================================================
// Denon publish all their IR codes:
// https://www.google.co.uk/search?q=DENON+MASTER+IR+Hex+Command+Sheet
// -> http://assets.denon.com/documentmaster/us/denon%20master%20ir%20hex.xls
// Having looked at the official Denon Pronto sheet and reverse engineered
// the timing values from it, it is obvious that Denon have a range of
// different timings and protocols ...the values here work for my AVR-3801 Amp!
// MSB first, no start bit, 5 address + 8 command + 2 frame + 1 stop bit - each frame 2 times
//
#define DENON_ADDRESS_BITS 5
#define DENON_COMMAND_BITS 8
#define DENON_FRAME_BITS 2 // 00/10 for 1. frame Denon/Sharp, inverted for autorepeat frame
#define DENON_BITS (DENON_ADDRESS_BITS + DENON_COMMAND_BITS + DENON_FRAME_BITS) // 15 - The number of bits in the command
#define DENON_UNIT 260
#define DENON_BIT_MARK DENON_UNIT // The length of a Bit:Mark
#define DENON_ONE_SPACE (7 * DENON_UNIT) // 1820 // The length of a Bit:Space for 1's
#define DENON_ZERO_SPACE (3 * DENON_UNIT) // 780 // The length of a Bit:Space for 0's
#define DENON_AUTO_REPEAT_SPACE 45000 // Every frame is auto repeated with a space period of 45 ms and the command inverted.
#define DENON_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
// for old decoder
#define DENON_HEADER_MARK DENON_UNIT // The length of the Header:Mark
#define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space
//+=============================================================================
void IRsend::sendSharp(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendDenon(aAddress, aCommand, aNumberOfRepeats, true);
}
/*
* Only for backwards compatibility
*/
void IRsend::sendDenonRaw(uint16_t aRawData, uint_fast8_t aNumberOfRepeats) {
sendDenon(aRawData >> (DENON_COMMAND_BITS + DENON_FRAME_BITS), aRawData & 0xFF, aNumberOfRepeats);
}
//+=============================================================================
void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendSharp) {
// Set IR carrier frequency
enableIROut(DENON_KHZ); // 38 kHz
// Shift command and add frame marker
uint16_t tCommand = aCommand << DENON_FRAME_BITS; // the lowest bits are 00 for Denon and 10 for Sharp
if (aSendSharp) {
tCommand |= 0x02;
}
uint16_t tData = tCommand | ((uint16_t) aAddress << (DENON_COMMAND_BITS + DENON_FRAME_BITS));
uint16_t tInvertedData = ((~tCommand) & 0x3FF) | (uint16_t) aAddress << (DENON_COMMAND_BITS + DENON_FRAME_BITS);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Data
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, tData, DENON_BITS,
PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
// Inverted autorepeat frame
delay(DENON_AUTO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, tInvertedData, DENON_BITS,
PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command with a fixed space gap
delay( DENON_AUTO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
bool IRrecv::decodeSharp() {
return decodeDenon();
}
//+=============================================================================
bool IRrecv::decodeDenon() {
// we have no start bit, so check for the exact amount of data bits
// Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * DENON_BITS) + 2) {
IR_DEBUG_PRINT(F("Denon: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 32"));
return false;
}
// Read the bits in
if (!decodePulseDistanceData(DENON_BITS, 1, DENON_BIT_MARK, DENON_ONE_SPACE, DENON_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
IR_DEBUG_PRINT(F("Denon: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Check for stop mark
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[(2 * DENON_BITS) + 1], DENON_HEADER_MARK)) {
IR_DEBUG_PRINT(F("Denon: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
uint8_t tFrameBits = decodedIRData.decodedRawData & 0x03;
decodedIRData.command = decodedIRData.decodedRawData >> DENON_FRAME_BITS;
decodedIRData.address = decodedIRData.command >> DENON_COMMAND_BITS;
uint8_t tCommand = decodedIRData.command & 0xFF;
decodedIRData.command = tCommand;
// check for autorepeated inverted command
if (decodedIRData.rawDataPtr->rawbuf[0] < ((DENON_AUTO_REPEAT_SPACE + (DENON_AUTO_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
repeatCount++;
if (tFrameBits == 0x3 || tFrameBits == 0x1) {
// We are in the auto repeated frame with the inverted command
decodedIRData.flags = IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;
// Check parity of consecutive received commands. There is no parity in one data set.
uint8_t tLastCommand = lastDecodedCommand;
if (tLastCommand != (uint8_t) (~tCommand)) {
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
}
// always take non inverted command
decodedIRData.command = tLastCommand;
}
if (repeatCount > 1) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
}
} else {
repeatCount = 0;
}
decodedIRData.numberOfBits = DENON_BITS;
if (tFrameBits == 1 || tFrameBits == 2) {
decodedIRData.protocol = SHARP;
} else {
decodedIRData.protocol = DENON;
}
return true;
}
bool IRrecv::decodeDenonOld(decode_results *aResults) {
// Check we have the right amount of data
if (decodedIRData.rawDataPtr->rawlen != 1 + 2 + (2 * DENON_BITS) + 1) {
return false;
}
// Check initial Mark+Space match
if (!matchMark(aResults->rawbuf[1], DENON_HEADER_MARK)) {
return false;
}
if (!matchSpace(aResults->rawbuf[2], DENON_HEADER_SPACE)) {
return false;
}
// Read the bits in
if (!decodePulseDistanceData(DENON_BITS, 3, DENON_BIT_MARK, DENON_ONE_SPACE, DENON_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
return false;
}
// Success
aResults->value = decodedIRData.decodedRawData;
aResults->bits = DENON_BITS;
aResults->decode_type = DENON;
decodedIRData.protocol = DENON;
return true;
}
void IRsend::sendDenon(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(DENON_KHZ);
#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))
Serial.println(
"The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats).");
#endif
// Header
mark(DENON_HEADER_MARK);
space(DENON_HEADER_SPACE);
// Data
sendPulseDistanceWidthData(DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
void IRsend::sendSharp(unsigned int aAddress, unsigned int aCommand) {
sendDenon(aAddress, aCommand, true, 0);
}
/** @}*/
#endif // _IR_DENON_HPP

View File

@@ -0,0 +1,46 @@
#include "IRremoteInt.h"
//==============================================================================
// DDDD IIIII SSSS H H
// D D I S H H
// D D I SSS HHHHH
// D D I S H H
// DDDD IIIII SSSS H H
//==============================================================================
// Sharp and DISH support by Todd Treece ( http://unionbridge.org/design/ircommand )
//
// The send function needs to be repeated 4 times
//
// Only send the last for characters of the hex.
// I.E. Use 0x1C10 instead of 0x0000000000001C10 as listed in the LIRC file.
//
// Here is the LIRC file I found that seems to match the remote codes from the
// oscilloscope:
// DISH NETWORK (echostar 301):
// http://lirc.sourceforge.net/remotes/echostar/301_501_3100_5100_58xx_59xx
#ifndef _IR_DISH_HPP
#define _IR_DISH_HPP
#define DISH_BITS 16
#define DISH_HEADER_MARK 400
#define DISH_HEADER_SPACE 6100
#define DISH_BIT_MARK 400
#define DISH_ONE_SPACE 1700
#define DISH_ZERO_SPACE 2800
#define DISH_REPEAT_SPACE 6200
//+=============================================================================
void IRsend::sendDISH(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(56);
mark(DISH_HEADER_MARK);
space(DISH_HEADER_SPACE);
sendPulseDistanceWidthData(DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
mark(DISH_HEADER_MARK); //added 26th March 2016, by AnalysIR ( https://www.AnalysIR.com )
IrReceiver.restartAfterSend();
}
#endif // _IR_DISH_HPP

View File

@@ -0,0 +1,372 @@
/*
* ir_DistanceProtocol.hpp
*
* This decoder tries to decode a pulse width or pulse distance protocol.
* 1. Analyze all space and mark length
* 2. Decide if we have an pulse width or distance protocol
* 3. Try to decode with the mark and space data found in step 1
* No data and address decoding, only raw data as result.
*
* Pulse distance data can be sent with the generic function:
* void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
* unsigned int aZeroSpaceMicros, uint32_t aData, uint8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false)
* The header must be sent manually with:
* IrSender.mark(MarkMicros)
* IrSender.space(SpaceMicros);
* see also: SendDemo example line 150
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_DISTANCE_HPP
#define _IR_DISTANCE_HPP
#include <Arduino.h>
// accept durations up to 50 * 50 (MICROS_PER_TICK) 2500 microseconds
#define DURATION_ARRAY_SIZE 50
// Switch the decoding according to your needs
#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_LSB_FIRST // this results in the same decodedRawData as e.g. the NEC and Kaseikyo/Panasonic decoder
//#define DISTANCE_DO_MSB_DECODING PROTOCOL_IS_MSB_FIRST // this resembles the JVC, Denon
#if defined(INFO) && !defined(LOCAL_INFO)
#define LOCAL_INFO
#else
#define LOCAL_INFO // This enables info output only for this file
#endif
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
//#include "LongUnion.h"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#Codings
#if defined(DEBUG)
void printDurations(uint8_t aArray[], uint8_t aMaxIndex) {
for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
if (i % 10 == 0) {
if (i == 0) {
Serial.print(' '); // indentation for the 0
} else {
Serial.println();
}
Serial.print(i);
Serial.print(F(":"));
}
Serial.print(F(" | "));
Serial.print(aArray[i]);
}
Serial.println();
}
#endif
/*
* @return false if more than 2 distinct duration values found
*/
bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIndex, uint8_t *aLongIndex) {
uint8_t tSum = 0;
uint16_t tWeightedSum = 0;
for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
uint8_t tCurrentDurations = aArray[i];
if (tCurrentDurations != 0) {
// Add it to sum and remove array content
tSum += tCurrentDurations;
tWeightedSum += (tCurrentDurations * i);
aArray[i] = 0;
}
if ((tCurrentDurations == 0 || i == aMaxIndex) && tSum != 0) {
// here we have a sum and a gap after the values
uint8_t tAggregateIndex = (tWeightedSum + (tSum / 2)) / tSum; // with rounding
aArray[tAggregateIndex] = tSum; // disabling this line increases code size by 2 - unbelievable!
// store aggregate for later decoding
if (*aShortIndex == 0) {
*aShortIndex = tAggregateIndex;
} else if (*aLongIndex == 0) {
*aLongIndex = tAggregateIndex;
} else {
// we have 3 bins => this is likely no pulse width or distance protocol. e.g. it can be RC5.
return false;
}
// initialize for next aggregation
tSum = 0;
tWeightedSum = 0;
}
}
return true;
}
/*
* Try to decode a pulse width or pulse distance protocol.
* 1. Analyze all space and mark length
* 2. Decide if we have an pulse width or distance protocol
* 3. Try to decode with the mark and space data found in step 1
* No data and address decoding, only raw data as result.
*/
bool IRrecv::decodeDistance() {
uint8_t tDurationArray[DURATION_ARRAY_SIZE];
/*
* Accept only protocols with at least 8 bits
*/
if (decodedIRData.rawDataPtr->rawlen < (2 * 8) + 4) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is less than 20"));
return false;
}
uint_fast8_t i;
// Reset duration array
memset(tDurationArray, 0, sizeof(tDurationArray));
uint8_t tMaxDurationIndex = 0;
/*
* Count number of mark durations. Skip leading start and trailing stop bit.
*/
for (i = 3; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
uint8_t tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (tDurationTicks < sizeof(tDurationArray)) {
tDurationArray[tDurationTicks]++;
if (tMaxDurationIndex < tDurationTicks) {
tMaxDurationIndex = tDurationTicks;
}
}
}
/*
* Aggregate mark counts to one duration bin
*/
uint8_t tMarkTicksShort = 0;
uint8_t tMarkTicksLong = 0;
bool tSuccess = aggregateArrayCounts(tDurationArray, tMaxDurationIndex, &tMarkTicksShort, &tMarkTicksLong);
#if defined(DEBUG)
Serial.println(F("Mark:"));
printDurations(tDurationArray, tMaxDurationIndex);
#endif
if (!tSuccess) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Mark aggregation failed, more than 2 distinct mark duration values found"));
}
// Reset duration array
memset(tDurationArray, 0, sizeof(tDurationArray));
/*
* Count number of space durations. Skip leading start and trailing stop bit.
*/
tMaxDurationIndex = 0;
for (i = 4; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
uint8_t tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (tDurationTicks < sizeof(tDurationArray)) {
tDurationArray[tDurationTicks]++;
if (tMaxDurationIndex < tDurationTicks) {
tMaxDurationIndex = tDurationTicks;
}
}
}
/*
* Aggregate space counts to one duration bin
*/
uint8_t tSpaceTicksShort = 0;
uint8_t tSpaceTicksLong = 0;
tSuccess = aggregateArrayCounts(tDurationArray, tMaxDurationIndex, &tSpaceTicksShort, &tSpaceTicksLong);
#if defined(DEBUG)
Serial.println(F("Space:"));
printDurations(tDurationArray, tMaxDurationIndex);
#endif
if (!tSuccess) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Space aggregation failed, more than 2 distinct space duration values found"));
return false;
}
// skip leading start and trailing stop bit.
uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 2;
decodedIRData.numberOfBits = tNumberOfBits;
/*
* Print characteristics of this protocol. Durations are in ticks.
* Number of bits, start bit, start pause, short mark, long mark, short space, long space
*
* NEC: 32, 180, 90, 11, 0, 11, 34
* Samsung32: 32, 90, 90, 11, 0, 11, 34
* LG: 28, 180, 84, 10, 0, 11, 32
* JVC: 16, 168, 84, 10, 0, 10, 32
* Kaseikyo: 48. 69, 35, 9, 0, 9, 26
* Sony: 12|15|20, 48, 12, 12, 24, 12, 0 // the only known pulse width protocol
*/
IR_DEBUG_PRINT(F("Protocol characteristics for a " STR(MICROS_PER_TICK) " us tick: "));
IR_DEBUG_PRINT(decodedIRData.numberOfBits);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawbuf[1]);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawbuf[2]);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINT(tMarkTicksShort);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINT(tMarkTicksLong);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINT(tSpaceTicksShort);
IR_DEBUG_PRINT(F(", "));
IR_DEBUG_PRINTLN(tSpaceTicksLong);
uint8_t tStartIndex = 3;
uint8_t tNumberOfAdditionalLong = (tNumberOfBits - 1) / 32;
/*
* decide, if we have an pulse width or distance protocol
*/
if (tSpaceTicksLong > 0) {
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
// if (decodePulseDistanceData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksShort * MICROS_PER_TICK,
// tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
// Serial.print(F("tNumberOfBits++ "));
// tNumberOfBits++;
// }
/*
* Here short and long space duration found. Decode in 32 bit chunks.
*/
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalLong; ++i) {
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
if (tNumberOfBitsForOneDecode > 32) {
tNumberOfBitsForOneDecode = 32;
}
if (!decodePulseDistanceData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksShort * MICROS_PER_TICK,
tSpaceTicksLong * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
} else {
#if defined(LOCAL_INFO)
/*
* Print usage :-)
*/
if (i == 0) {
// Print this only once
Serial.println();
Serial.println(F("PULSE_DISTANCE: Send with:"));
Serial.println(F(" IrSender.enableIROut(38);"));
Serial.print(F(" IrSender.mark("));
Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
Serial.println(F(");"));
Serial.print(F(" IrSender.space("));
Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
Serial.println(F(");"));
}
Serial.print(F(" IrSender.sendPulseDistanceWidthData("));
Serial.print(tMarkTicksShort * MICROS_PER_TICK); // aOneMarkMicros
Serial.print(F(", "));
Serial.print(tSpaceTicksLong * MICROS_PER_TICK); // aOneSpaceMicros
Serial.print(F(", "));
Serial.print(tMarkTicksShort * MICROS_PER_TICK); // aZeroMarkMicros
Serial.print(F(", "));
Serial.print(tSpaceTicksShort * MICROS_PER_TICK); // aZeroSpaceMicros
Serial.print(F(", 0x"));
Serial.print(decodedIRData.decodedRawData, HEX); // aData
if (tNumberOfBits < 32) {
Serial.print(F(", "));
Serial.print(tNumberOfBits); // aNumberOfBits
} else {
Serial.print(F(", 32"));
}
if (DISTANCE_DO_MSB_DECODING) {
Serial.print(F(", true, ")); // aMSBfirst
} else {
Serial.print(F(", false, ")); // aMSBfirst
}
if (i == tNumberOfAdditionalLong) {
Serial.println(F("true);")); // aSendStopBit - true for last data set
Serial.println();
} else {
Serial.println(F("false);"));// aSendStopBit
}
#endif
tStartIndex += 64;
tNumberOfBits -= 32;
}
}
// Store ticks used for decoding in extra
decodedIRData.extra = (tSpaceTicksShort << 8) | tSpaceTicksLong;
decodedIRData.protocol = PULSE_DISTANCE;
} else {
if (tMarkTicksLong == 0) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE: "));
IR_DEBUG_PRINTLN(F("Only 1 distinct duration value for each space and mark found"));
return false;
}
//#define SUPPORT_PULSE_WIDTH_DECODING
#if defined(SUPPORT_PULSE_WIDTH_DECODING) // The only known pulse width protocol is Sony
// // check if last bit can be decoded as data or not, in this case take it as a stop bit
// if (decodePulseWidthData(1, decodedIRData.rawDataPtr->rawlen - 3, tMarkTicksLong * MICROS_PER_TICK,
// tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
// tNumberOfBits++;
// }
// decode without leading start bit. Currently only seen for sony protocol
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalLong; ++i) {
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
if (tNumberOfBitsForOneDecode > 32) {
tNumberOfBitsForOneDecode = 32;
}
if (!decodePulseWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkTicksLong * MICROS_PER_TICK,
tMarkTicksShort * MICROS_PER_TICK, tSpaceTicksShort * MICROS_PER_TICK, DISTANCE_DO_MSB_DECODING)) {
IR_DEBUG_PRINT(F("PULSE_WIDTH: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
tStartIndex += 64;
tNumberOfBits -= 32;
}
// Store ticks used for decoding in extra
decodedIRData.extra = (tMarkTicksShort << 8) | tMarkTicksLong;
decodedIRData.protocol = PULSE_WIDTH;
#endif
}
if (DISTANCE_DO_MSB_DECODING) {
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO;
} else {
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO;
}
return true;
}
/** @}*/
#endif // _IR_DISTANCE_HPP

View File

@@ -0,0 +1,242 @@
/*
* ir_JVC.hpp
*
* Contains functions for receiving and sending JVC IR Protocol in "raw" and standard format with 8 bit address and 8 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2021 Kristian Lauszus, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_JVC_HPP
#define _IR_JVC_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// JJJJJ V V CCCC
// J V V C
// J V V C
// J J V V C
// J V CCCC
//==============================================================================
// https://www.sbprojects.net/knowledge/ir/jvc.php
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#JVC
// IRP: {38k,525}<1,-1|1,-3>(16,-8,(D:8,F:8,1,-45)+)
// LSB first, 1 start bit + 8 bit address + 8 bit command + 1 stop bit.
// The JVC protocol repeats by skipping the header mark and space -> this leads to a poor repeat detection for JVC protocol.
#define JVC_ADDRESS_BITS 8 // 8 bit address
#define JVC_COMMAND_BITS 8 // Command
#define JVC_BITS (JVC_ADDRESS_BITS + JVC_COMMAND_BITS) // 16 - The number of bits in the protocol
#define JVC_UNIT 526 // 20 periods of 38 kHz (526.315789)
#define JVC_HEADER_MARK (16 * JVC_UNIT) // 8400
#define JVC_HEADER_SPACE (8 * JVC_UNIT) // 4200
#define JVC_BIT_MARK JVC_UNIT // The length of a Bit:Mark
#define JVC_ONE_SPACE (3 * JVC_UNIT) // 1578 - The length of a Bit:Space for 1's
#define JVC_ZERO_SPACE JVC_UNIT // The length of a Bit:Space for 0's
#define JVC_REPEAT_SPACE (uint16_t)(45 * JVC_UNIT) // 23625 - Commands are repeated with a distance of 23 ms for as long as the key on the remote control is held down.
//+=============================================================================
// JVC does NOT repeat by sending a separate code (like NEC does).
// The JVC protocol repeats by skipping the header.
//
void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(JVC_KHZ); // 38 kHz
// Header
mark(JVC_HEADER_MARK);
space(JVC_HEADER_SPACE);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Address + command
sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE,
aAddress | (aCommand << JVC_ADDRESS_BITS), JVC_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(JVC_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
/*
* First check for right data length
* Next check start bit
* Next try the decode
*/
bool IRrecv::decodeJVC() {
// Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark. +2 is for repeats
if (decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 4) && decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 2)) {
IR_DEBUG_PRINT(F("JVC: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 34 or 36"));
return false;
}
if (decodedIRData.rawDataPtr->rawlen == ((2 * JVC_BITS) + 2)) {
/*
* Check for repeat
* Check leading space and first and last mark length
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < ((JVC_REPEAT_SPACE + (JVC_REPEAT_SPACE / 4) / MICROS_PER_TICK))
&& matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_BIT_MARK)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen - 1], JVC_BIT_MARK)) {
/*
* We have a repeat here, so do not check for start bit
*/
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
decodedIRData.address = lastDecodedAddress;
decodedIRData.command = lastDecodedCommand;
decodedIRData.protocol = JVC;
}
} else {
// Check header "mark" and "space"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_HEADER_MARK)
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], JVC_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("JVC: "));
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
return false;
}
if (!decodePulseDistanceData(JVC_BITS, 3, JVC_BIT_MARK, JVC_ONE_SPACE, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("JVC: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
uint8_t tCommand = decodedIRData.decodedRawData >> JVC_ADDRESS_BITS; // upper 8 bits of LSB first value
uint8_t tAddress = decodedIRData.decodedRawData & 0xFF; // lowest 8 bit of LSB first value
decodedIRData.command = tCommand;
decodedIRData.address = tAddress;
decodedIRData.numberOfBits = JVC_BITS;
decodedIRData.protocol = JVC;
}
return true;
}
bool IRrecv::decodeJVCMSB(decode_results *aResults) {
unsigned int offset = 1; // Skip first space
// Check for repeat
if ((aResults->rawlen - 1 == 33) && matchMark(aResults->rawbuf[offset], JVC_BIT_MARK)
&& matchMark(aResults->rawbuf[aResults->rawlen - 1], JVC_BIT_MARK)) {
aResults->bits = 0;
aResults->value = 0xFFFFFFFF;
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
decodedIRData.protocol = JVC;
return true;
}
// Initial mark
if (!matchMark(aResults->rawbuf[offset], JVC_HEADER_MARK)) {
return false;
}
offset++;
// Check we have enough data - +3 for start bit mark and space + stop bit mark
if (aResults->rawlen <= (2 * JVC_BITS) + 3) {
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(aResults->rawlen);
IR_DEBUG_PRINTLN(F(" is too small. >= 36 is required."));
return false;
}
// Initial space
if (!matchSpace(aResults->rawbuf[offset], JVC_HEADER_SPACE)) {
return false;
}
offset++;
if (!decodePulseDistanceData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, JVC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
return false;
}
// Stop bit
if (!matchMark(aResults->rawbuf[offset + (2 * JVC_BITS)], JVC_BIT_MARK)) {
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
aResults->value = decodedIRData.decodedRawData;
aResults->bits = JVC_BITS;
aResults->decode_type = JVC;
decodedIRData.protocol = JVC;
return true;
}
/**
* With Send sendJVCMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte.
* Or write it as one binary string and reverse/mirror it.
* Example:
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.
* 0xCB340102 is binary 11001011001101000000000100000010.
* 0x40802CD3 is binary 01000000100000000010110011010011.
* If you read the first binary sequence backwards (right to left), you get the second sequence.
*/
void IRsend::sendJVCMSB(unsigned long data, int nbits, bool repeat) {
// Set IR carrier frequency
enableIROut(JVC_KHZ);
// Only send the Header if this is NOT a repeat command
if (!repeat) {
mark(JVC_HEADER_MARK);
space(JVC_HEADER_SPACE);
}
// Old version with MSB first Data
sendPulseDistanceWidthData(JVC_BIT_MARK, JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_JVC_HPP

View File

@@ -0,0 +1,336 @@
/*
* ir_Kaseikyo.hpp
*
* Contains functions for receiving and sending Kaseikyo/Panasonic IR Protocol in "raw" and standard format with 16 bit address + 8 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_KASEIKYO_HPP
#define _IR_KASEIKYO_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
#include "LongUnion.h"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// PPPP AAA N N AAA SSSS OOO N N IIIII CCCC
// P P A A NN N A A S O O NN N I C
// PPPP AAAAA N N N AAAAA SSS O O N N N I C
// P A A N NN A A S O O N NN I C
// P A A N N A A SSSS OOO N N IIIII CCCC
//==============================================================================
// see: http://www.hifi-remote.com/johnsfine/DecodeIR.html#Panasonic and http://www.hifi-remote.com/johnsfine/DecodeIR.html#Kaseikyo
// see: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152
// The first two (8-bit) bytes contains the vendor code.
// There are multiple interpretations of the next fields:
// 1. IRP notation: {37k,432}<1,-1|1,-3>(8,-4,M:8,N:8,X:4,D:4,S:8,F:8,G:8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4}
// 2. The next two bytes are 4 independent 4-bit fields or Device and Subdevice
// The second to last byte is the function and the last byte is xor of the three bytes before it.
// 0_______ 1_______ 2______ 3_______ 4_______ 5
// 76543210 76543210 76543210 76543210 76543210 76543210
// 00000010 00100000 Dev____ Sub Dev Fun____ XOR( B2, B3, B4)
// 3. LSB first, start bit + 16 Vendor + 4 Parity(of vendor) + 4 Genre1 + 4 Genre2 + 10 Command + 2 ID + 8 Parity + stop bit
//
// We reduce it to: start bit + 16 Vendor + 16 Address + 8 Command + 8 Parity + stop bit
//
#define KASEIKYO_VENDOR_ID_BITS 16
#define KASEIKYO_VENDOR_ID_PARITY_BITS 4
#define KASEIKYO_ADDRESS_BITS 12
#define KASEIKYO_COMMAND_BITS 8
#define KASEIKYO_PARITY_BITS 8
#define KASEIKYO_BITS (KASEIKYO_VENDOR_ID_BITS + KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS)
#define KASEIKYO_UNIT 432 // 16 pulses of 37 kHz (432,432432) - Pronto 0x70 / 0x10
#define KASEIKYO_HEADER_MARK (8 * KASEIKYO_UNIT) // 3456
#define KASEIKYO_HEADER_SPACE (4 * KASEIKYO_UNIT) // 1728
#define KASEIKYO_BIT_MARK KASEIKYO_UNIT
#define KASEIKYO_ONE_SPACE (3 * KASEIKYO_UNIT) // 1296
#define KASEIKYO_ZERO_SPACE KASEIKYO_UNIT
#define KASEIKYO_AVERAGE_DURATION 56000
#define KASEIKYO_REPEAT_PERIOD 130000
#define KASEIKYO_REPEAT_SPACE (KASEIKYO_REPEAT_PERIOD - KASEIKYO_AVERAGE_DURATION) // 74 ms
// for old decoder
#define KASEIKYO_DATA_BITS 32
//+=============================================================================
/*
* Send with LSB first
* Address is sub-device << 8 + device
*/
void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint16_t aVendorCode) {
// Set IR carrier frequency
enableIROut(KASEIKYO_KHZ); // 37 kHz
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Header
mark(KASEIKYO_HEADER_MARK);
space(KASEIKYO_HEADER_SPACE);
// Vendor ID
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aVendorCode,
KASEIKYO_VENDOR_ID_BITS, PROTOCOL_IS_LSB_FIRST);
// Vendor Parity
uint8_t tVendorParity = aVendorCode ^ (aVendorCode >> 8);
tVendorParity = (tVendorParity ^ (tVendorParity >> 4)) & 0xF;
LongUnion tSendValue;
tSendValue.UWord.LowWord = aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS;
tSendValue.UByte.LowByte |= tVendorParity; // set low nibble to parity
tSendValue.UByte.MidHighByte = aCommand;
tSendValue.UByte.HighByte = aCommand ^ tSendValue.UByte.LowByte ^ tSendValue.UByte.MidLowByte; // Parity
// Send address (device and subdevice) + command + parity + Stop bit
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, tSendValue.ULong,
KASEIKYO_ADDRESS_BITS + KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(KASEIKYO_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
/**
* Stub using Kaseikyo with PANASONIC_VENDOR_ID_CODE
*/
void IRsend::sendPanasonic(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, PANASONIC_VENDOR_ID_CODE);
}
/**
* Stub using Kaseikyo with DENON_VENDOR_ID_CODE
*/
void IRsend::sendKaseikyo_Denon(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, DENON_VENDOR_ID_CODE);
}
/**
* Stub using Kaseikyo with MITSUBISHI_VENDOR_ID_CODE
*/
void IRsend::sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, MITSUBISHI_VENDOR_ID_CODE);
}
/**
* Stub using Kaseikyo with SHARP_VENDOR_ID_CODE
*/
void IRsend::sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, SHARP_VENDOR_ID_CODE);
}
/**
* Stub using Kaseikyo with JVC_VENDOR_ID_CODE
*/
void IRsend::sendKaseikyo_JVC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendKaseikyo(aAddress, aCommand, aNumberOfRepeats, JVC_VENDOR_ID_CODE);
}
/*
* Tested with my Panasonic DVD/TV remote
*/
bool IRrecv::decodeKaseikyo() {
decode_type_t tProtocol;
// Check we have enough data (100)- +4 for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != ((2 * KASEIKYO_BITS) + 4)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 100"));
return false;
}
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], KASEIKYO_HEADER_MARK)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("Header mark length is wrong"));
return false;
}
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[2], KASEIKYO_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
// decode Vendor ID
if (!decodePulseDistanceData(KASEIKYO_VENDOR_ID_BITS, 3, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_ZERO_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("Vendor ID decode failed"));
return false;
}
uint16_t tVendorId = decodedIRData.decodedRawData;
if (tVendorId == PANASONIC_VENDOR_ID_CODE) {
tProtocol = PANASONIC;
} else if (tVendorId == SHARP_VENDOR_ID_CODE) {
tProtocol = KASEIKYO_SHARP;
} else if (tVendorId == DENON_VENDOR_ID_CODE) {
tProtocol = KASEIKYO_DENON;
} else if (tVendorId == JVC_VENDOR_ID_CODE) {
tProtocol = KASEIKYO_JVC;
} else if (tVendorId == MITSUBISHI_VENDOR_ID_CODE) {
tProtocol = KASEIKYO_MITSUBISHI;
} else {
tProtocol = KASEIKYO;
}
// Vendor Parity
uint8_t tVendorParity = tVendorId ^ (tVendorId >> 8);
tVendorParity = (tVendorParity ^ (tVendorParity >> 4)) & 0xF;
// decode address (device and subdevice) + command + parity
if (!decodePulseDistanceData(
KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
3 + (2 * KASEIKYO_VENDOR_ID_BITS), KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE,
KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINTLN(F("Address, command + parity decode failed"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
LongUnion tValue;
tValue.ULong = decodedIRData.decodedRawData;
decodedIRData.address = (tValue.UWord.LowWord >> KASEIKYO_VENDOR_ID_PARITY_BITS); // remove vendor parity
decodedIRData.command = tValue.UByte.MidHighByte;
uint8_t tParity = tValue.UByte.LowByte ^ tValue.UByte.MidLowByte ^ tValue.UByte.MidHighByte;
if (tVendorParity != (tValue.UByte.LowByte & 0xF)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINT(F("4 bit VendorID Parity is not correct. expected=0x"));
IR_DEBUG_PRINT(tVendorParity, HEX);
IR_DEBUG_PRINT(F(" received=0x"));
IR_DEBUG_PRINT(decodedIRData.decodedRawData, HEX);
IR_DEBUG_PRINT(F(" VendorID=0x"));
IR_DEBUG_PRINTLN(tVendorId, HEX);
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
}
if (tProtocol != KASEIKYO) {
decodedIRData.flags |= IRDATA_FLAGS_EXTRA_INFO;
decodedIRData.extra = tVendorId; // Store vendor ID
}
if (tValue.UByte.HighByte != tParity) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINT(F("8 bit Parity is not correct. expected=0x"));
IR_DEBUG_PRINT(tParity, HEX);
IR_DEBUG_PRINT(F(" received=0x"));
IR_DEBUG_PRINT(decodedIRData.decodedRawData >> KASEIKYO_COMMAND_BITS, HEX);
IR_DEBUG_PRINT(F(" address=0x"));
IR_DEBUG_PRINT(decodedIRData.address, HEX);
IR_DEBUG_PRINT(F(" command=0x"));
IR_DEBUG_PRINTLN(decodedIRData.command, HEX);
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
}
// check for repeat
if (decodedIRData.rawDataPtr->rawbuf[0] < (KASEIKYO_REPEAT_PERIOD / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
}
decodedIRData.protocol = tProtocol;
decodedIRData.numberOfBits = KASEIKYO_BITS;
return true;
}
/**
* Old MSB first decoder
*/
bool IRrecv::decodePanasonicMSB(decode_results *aResults) {
unsigned int offset = 1;
if (aResults->rawlen < (2 * KASEIKYO_BITS) + 2) {
return false;
}
if (!matchMark(aResults->rawbuf[offset], KASEIKYO_HEADER_MARK)) {
return false;
}
offset++;
if (!matchMark(aResults->rawbuf[offset], KASEIKYO_HEADER_SPACE)) {
return false;
}
offset++;
// decode address
if (!decodePulseDistanceData(KASEIKYO_ADDRESS_BITS + KASEIKYO_DATA_BITS, offset, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE,
KASEIKYO_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
return false;
}
aResults->bits = KASEIKYO_BITS;
aResults->value = decodedIRData.decodedRawData;
aResults->address = PANASONIC_VENDOR_ID_CODE;
aResults->decode_type = PANASONIC;
decodedIRData.protocol = PANASONIC;
return true;
}
/**
* Old version with MSB first data
*/
void IRsend::sendPanasonic(uint16_t aAddress, uint32_t aData) {
// Set IR carrier frequency
enableIROut(KASEIKYO_KHZ); // 36.7kHz is the correct frequency
// Header
mark(KASEIKYO_HEADER_MARK);
space(KASEIKYO_HEADER_SPACE);
// Old version with MSB first Data Address
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aAddress,
KASEIKYO_ADDRESS_BITS, PROTOCOL_IS_MSB_FIRST);
// Old version with MSB first Data Data + stop bit
sendPulseDistanceWidthData(KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, aData,
KASEIKYO_DATA_BITS, PROTOCOL_IS_MSB_FIRST);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_KASEIKYO_HPP

View File

@@ -0,0 +1,325 @@
/*
* ir_LG.hpp
*
* Contains functions for receiving and sending LG IR Protocol in "raw" and standard format with 16 or 8 bit address and 8 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2021 Darryl Smith, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_LG_HPP
#define _IR_LG_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// L GGGG
// L G
// L G GG
// L G G
// LLLLL GGG
//==============================================================================
// LG originally added by Darryl Smith (based on the JVC protocol)
// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/LGAirConditionerSendDemo
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#LGAIR
// MSB first, 1 start bit + 8 bit address + 16 bit command + 4 bit checksum + 1 stop bit (28 data bits).
// Bit and repeat timing is like NEC
// LG2 has different header timing and a shorter bit time
/*
* LG remote measurements: Type AKB73315611, Ver1.1 from 2011.03.01
* Internal crystal: 4 MHz
* Header: 8.9 ms mark 4.15 ms space
* Data: 500 / 540 and 500 / 1580;
* Clock is nor synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark
* Duty: 9 us on 17 us off => around 33 % duty
* NO REPEAT: If value like temperature has changed during long press, the last value is send at button release.
* If you do a double press, the next value can be sent after around 118 ms. Tested with the fan button.
*
* The codes of the LG air conditioner are documented in https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/ac_LG.cpp
*/
#define LG_ADDRESS_BITS 8
#define LG_COMMAND_BITS 16
#define LG_CHECKSUM_BITS 4
#define LG_BITS (LG_ADDRESS_BITS + LG_COMMAND_BITS + LG_CHECKSUM_BITS) // 28
#define LG_UNIT 500 // 19 periods of 38 kHz
#define LG_HEADER_MARK (18 * LG_UNIT) // 9000
#define LG_HEADER_SPACE 4200 // 84
#define LG2_HEADER_MARK (6 * LG_UNIT) // 3000
#define LG2_HEADER_SPACE (19 * LG_UNIT) // 9500
#define LG_BIT_MARK LG_UNIT
#define LG_ONE_SPACE 1580 // 60 periods of 38 kHz
#define LG_ZERO_SPACE 550
#define LG_REPEAT_HEADER_SPACE (4 * LG_UNIT) // 2250
#define LG_AVERAGE_DURATION 58000 // LG_HEADER_MARK + LG_HEADER_SPACE + 32 * 2,5 * LG_UNIT) + LG_UNIT // 2.5 because we assume more zeros than ones
#define LG_REPEAT_DURATION (LG_HEADER_MARK + LG_REPEAT_HEADER_SPACE + LG_BIT_MARK)
#define LG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
#define LG_REPEAT_SPACE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms
//+=============================================================================
/*
* Send repeat
* Repeat commands should be sent in a 110 ms raster.
*/
void IRsend::sendLGRepeat(bool aUseLG2Protocol) {
enableIROut(LG_KHZ); // 38 kHz
if (aUseLG2Protocol) {
mark(LG2_HEADER_MARK);
} else {
mark(LG_HEADER_MARK);
}
space(LG_REPEAT_HEADER_SPACE);
mark(LG_BIT_MARK);
IrReceiver.restartAfterSend();
}
/**
* Repeat commands should be sent in a 110 ms raster.
* There is NO delay after the last sent repeat!
* @param aUseLG2Protocol if true use LG2 protocol, which has a different header
*/
void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
uint32_t tRawData = ((uint32_t) aAddress << (LG_COMMAND_BITS + LG_CHECKSUM_BITS)) | ((uint32_t) aCommand << LG_CHECKSUM_BITS);
/*
* My guess of the 4 bit checksum
* Addition of all 4 nibbles of the 16 bit command
*/
uint8_t tChecksum = 0;
uint16_t tTempForChecksum = aCommand;
for (int i = 0; i < 4; ++i) {
tChecksum += tTempForChecksum & 0xF; // add low nibble
tTempForChecksum >>= 4; // shift by a nibble
}
tRawData |= (tChecksum & 0xF);
sendLGRaw(tRawData, aNumberOfRepeats, aIsRepeat, aUseLG2Protocol);
}
/*
* Here you can put your raw data, even one with "wrong" checksum
*/
void IRsend::sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat, bool aUseLG2Protocol) {
if (aIsRepeat) {
sendLGRepeat();
return;
}
// Set IR carrier frequency
enableIROut(LG_KHZ);
// Header
if (aUseLG2Protocol) {
mark(LG2_HEADER_MARK);
space(LG2_HEADER_SPACE);
// MSB first
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, aRawData, LG_BITS, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
} else {
mark(LG_HEADER_MARK);
space(LG_HEADER_SPACE);
// MSB first
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, aRawData, LG_BITS, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
}
for (uint_fast8_t i = 0; i < aNumberOfRepeats; ++i) {
// send repeat in a 110 ms raster
if (i == 0) {
delay(LG_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
} else {
delay((LG_REPEAT_PERIOD - LG_REPEAT_DURATION) / MICROS_IN_ONE_MILLI);
}
// send repeat
sendLGRepeat(aUseLG2Protocol);
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
// LGs has a repeat like NEC
//
/*
* First check for right data length
* Next check start bit
* Next try the decode
* Last check stop bit
*/
bool IRrecv::decodeLG() {
decode_type_t tProtocol = LG;
uint16_t tHeaderSpace = LG_HEADER_SPACE;
// Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 60 or 4"));
return false;
}
// Check header "mark" this must be done for repeat and data
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG_HEADER_MARK)) {
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINTLN(F("Header mark is wrong"));
return false;
} else {
tProtocol = LG2;
tHeaderSpace = LG2_HEADER_SPACE;
}
}
// Check for repeat - here we have another header space length
if (decodedIRData.rawDataPtr->rawlen == 4) {
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.address = lastDecodedAddress;
decodedIRData.command = lastDecodedCommand;
decodedIRData.protocol = lastDecodedProtocol;
return true;
}
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINT(F("Repeat header space is wrong"));
return false;
}
// Check command header space
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], tHeaderSpace)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
if (!decodePulseDistanceData(LG_BITS, 3, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LG_BITS)], LG_BIT_MARK)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.command = (decodedIRData.decodedRawData >> LG_CHECKSUM_BITS) & 0xFFFF;
decodedIRData.address = decodedIRData.decodedRawData >> (LG_COMMAND_BITS + LG_CHECKSUM_BITS); // first 8 bit
/*
* My guess of the checksum
*/
uint8_t tChecksum = 0;
uint16_t tTempForChecksum = decodedIRData.command;
for (int i = 0; i < 4; ++i) {
tChecksum += tTempForChecksum & 0xF; // add low nibble
tTempForChecksum >>= 4; // shift by a nibble
}
// Checksum check
if ((tChecksum & 0xF) != (decodedIRData.decodedRawData & 0xF)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINT(F("4 bit checksum is not correct. expected=0x"));
IR_DEBUG_PRINT(tChecksum, HEX);
IR_DEBUG_PRINT(F(" received=0x"));
IR_DEBUG_PRINT((decodedIRData.decodedRawData & 0xF), HEX);
IR_DEBUG_PRINT(F(" data=0x"));
IR_DEBUG_PRINTLN(decodedIRData.command, HEX);
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
}
decodedIRData.protocol = tProtocol; // LG or LG2
decodedIRData.numberOfBits = LG_BITS;
return true;
}
bool IRrecv::decodeLGMSB(decode_results *aResults) {
unsigned int offset = 1; // Skip first space
// Check we have enough data (60) - +4 for initial gap, start bit mark and space + stop bit mark
if (aResults->rawlen != (2 * LG_BITS) + 4) {
return false;
}
// Initial mark/space
if (!matchMark(aResults->rawbuf[offset], LG_HEADER_MARK)) {
return false;
}
offset++;
if (!matchSpace(aResults->rawbuf[offset], LG_HEADER_SPACE)) {
return false;
}
offset++;
if (!decodePulseDistanceData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
return false;
}
// Stop bit
if (!matchMark(aResults->rawbuf[offset + (2 * LG_BITS)], LG_BIT_MARK)) {
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
aResults->value = decodedIRData.decodedRawData;
aResults->bits = LG_BITS;
aResults->decode_type = LG;
decodedIRData.protocol = LG;
return true;
}
//+=============================================================================
void IRsend::sendLG(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(LG_KHZ);
#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__))
Serial.println(
"The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).");
#endif
// Header
mark(LG_HEADER_MARK);
space(LG_HEADER_SPACE);
// mark(LG_BIT_MARK);
// Data + stop bit
sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_LG_HPP

View File

@@ -0,0 +1,227 @@
/*
* ir_Lego.hpp
*
* Contains functions for receiving and sending Lego Power Functions IR Protocol
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_LEGO_HPP
#define _IR_LEGO_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// L EEEEEE EEEE OOOO
// L E E O O
// L EEEE E EEE O O
// L E E E O O
// LLLLLL EEEEEE EEEE OOOO
//==============================================================================
// from LEGO Power Functions RC Manual 26.02.2010 Version 1.20
// https://github.com/jurriaan/Arduino-PowerFunctions/raw/master/LEGO_Power_Functions_RC_v120.pdf
// https://oberguru.net/elektronik/ir/codes/lego_power_functions_train.lircd.conf
//
// To ensure correct detection of IR messages six 38 kHz cycles are transmitted as mark.
// Low bit consists of 6 cycles of IR and 10 “cycles” of pause,
// high bit of 6 cycles IR and 21 “cycles” of pause and start bit of 6 cycles IR and 39 “cycles” of pause.
// Low bit range 316 - 526 us
// High bit range 526 947 us
// Start/stop bit range 947 1579 us
// If tm is the maximum message length (16ms) and Ch is the channel number, then
// The delay before transmitting the first message is: (4 Ch)*tm
// The time from start to start for the next 2 messages is: 5*tm
// The time from start to start for the following messages is: (6 + 2*Ch)*tm
// Supported Devices
// LEGO Power Functions IR Receiver 8884
// MSB first, 1 start bit + 4 bit channel, 4 bit mode + 4 bit command + 4 bit parity + 1 stop bit.
#define LEGO_CHANNEL_BITS 4
#define LEGO_MODE_BITS 4
#define LEGO_COMMAND_BITS 4
#define LEGO_PARITY_BITS 4
#define LEGO_BITS (LEGO_CHANNEL_BITS + LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS)
#define LEGO_HEADER_MARK 158 // 6 cycles
#define LEGO_HEADER_SPACE 1026 // 39 cycles
#define LEGO_BIT_MARK 158 // 6 cycles
#define LEGO_ONE_SPACE 553 // 21 cycles
#define LEGO_ZERO_SPACE 263 // 10 cycles
#define LEGO_AVERAGE_DURATION 11000 // LEGO_HEADER_MARK + LEGO_HEADER_SPACE + 16 * 600 + 158
#define LEGO_AUTO_REPEAT_PERIOD_MIN 110000 // Every frame is auto repeated 5 times.
#define LEGO_AUTO_REPEAT_PERIOD_MAX 230000 // space for channel 3
/*
* Compatibility function for legacy code, this calls the send raw data function
*/
void IRsend::sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times) {
sendLegoPowerFunctions(aRawData, (aRawData >> (LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS)) & 0x3, aDoSend5Times);
}
/*
* Here we process the structured data, and call the send raw data function
*/
void IRsend::sendLegoPowerFunctions(uint8_t aChannel, uint8_t aCommand, uint8_t aMode, bool aDoSend5Times) {
aChannel &= 0x0F; // allow toggle and escape bits too
aCommand &= 0x0F;
aMode &= 0x0F;
uint8_t tParity = 0xF ^ aChannel ^ aMode ^ aCommand;
// send 4 bit channel, 4 bit mode, 4 bit command, 4 bit parity
uint16_t tRawData = (((aChannel << LEGO_MODE_BITS) | aMode) << (LEGO_COMMAND_BITS + LEGO_PARITY_BITS))
| (aCommand << LEGO_PARITY_BITS) | tParity;
sendLegoPowerFunctions(tRawData, aChannel, aDoSend5Times);
}
void IRsend::sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times) {
enableIROut(38);
IR_DEBUG_PRINT(F("sendLego aRawData=0x"));
IR_DEBUG_PRINTLN(aRawData, HEX);
aChannel &= 0x03; // we have 4 channels
uint_fast8_t tNumberOfCommands = 1;
if (aDoSend5Times) {
tNumberOfCommands = 5;
}
// required for repeat timing, see http://www.hackvandedam.nl/blog/?page_id=559
uint8_t tRepeatPeriod = (110 - (LEGO_AVERAGE_DURATION / MICROS_IN_ONE_MILLI)) + (aChannel * 40); // from 100 to 220
while (tNumberOfCommands > 0) {
// Header
mark(LEGO_HEADER_MARK);
space(LEGO_HEADER_SPACE);
sendPulseDistanceWidthData(LEGO_BIT_MARK, LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, aRawData, LEGO_BITS,
PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command with a fixed space gap
delay(tRepeatPeriod);
}
}
IrReceiver.restartAfterSend();
}
/*
* Mode is stored in the upper nibble of command
*/
bool IRrecv::decodeLegoPowerFunctions() {
// Check header "mark"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LEGO_HEADER_MARK)) {
// no debug output, since this check is mainly to determine the received protocol
return false;
}
// Check we have enough data - +4 for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * LEGO_BITS) + 4) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}
// Check header "space"
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LEGO_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
if (!decodePulseDistanceData(LEGO_BITS, 3, LEGO_BIT_MARK, LEGO_ONE_SPACE, LEGO_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LEGO_BITS)], LEGO_BIT_MARK)) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
uint16_t tDecodedValue = decodedIRData.decodedRawData;
uint8_t tToggleEscapeChannel = tDecodedValue >> (LEGO_MODE_BITS + LEGO_COMMAND_BITS + LEGO_PARITY_BITS);
uint8_t tMode = (tDecodedValue >> (LEGO_COMMAND_BITS + LEGO_PARITY_BITS)) & 0xF;
uint8_t tData = (tDecodedValue >> LEGO_PARITY_BITS) & 0xF; // lego calls this field "data"
uint8_t tParityReceived = tDecodedValue & 0xF;
// This is parity as defined in the specifications
// But in some scans I saw 0x9 ^ .. as parity formula
uint8_t tParityComputed = 0xF ^ tToggleEscapeChannel ^ tMode ^ tData;
// parity check
if (tParityReceived != tParityComputed) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINT(F("Parity is not correct. expected=0x"));
IR_DEBUG_PRINT(tParityComputed, HEX);
IR_DEBUG_PRINT(F(" received=0x"));
IR_DEBUG_PRINT(tParityReceived, HEX);
IR_DEBUG_PRINT(F(", raw=0x"));
IR_DEBUG_PRINT(tDecodedValue, HEX);
IR_DEBUG_PRINT(F(", 3 nibbles are 0x"));
IR_DEBUG_PRINT(tToggleEscapeChannel, HEX);
IR_DEBUG_PRINT(F(", 0x"));
IR_DEBUG_PRINT(tMode, HEX);
IR_DEBUG_PRINT(F(", 0x"));
IR_DEBUG_PRINTLN(tData, HEX);
// might not be an error, so just continue
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_MSB_FIRST;
}
/*
* Check for autorepeat (should happen 4 times for one press)
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
}
decodedIRData.address = tToggleEscapeChannel;
decodedIRData.command = tData | tMode << LEGO_COMMAND_BITS;
decodedIRData.protocol = LEGO_PF;
decodedIRData.numberOfBits = LEGO_BITS;
return true;
}
/** @}*/
#endif // _IR_LEGO_HPP

View File

@@ -0,0 +1,179 @@
/*
* ir_MagiQuest.hpp
*
* Contains functions for receiving and sending MagiQuest Protocol
* Based off the Magiquest fork of Arduino-IRremote by mpflaga https://github.com/mpflaga/Arduino-IRremote/
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2022 E. Stuart Hicks <ehicks@binarymagi.com>, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_MAGIQUEST_HPP
#define _IR_MAGIQUEST_HPP
#include <Arduino.h>
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
//
//==============================================================================
//
// M A G I Q U E S T
//
//==============================================================================
// MSB first, 8 Start bits (zero), 32 wand id bits, 16 magnitude bits, one stop bit
// Not all start bits must be received, since protocol is MSB first and so the LSB ends up always at the right position.
#if !defined (DOXYGEN)
// MagiQuest packet is both Wand ID and magnitude of swish and flick
union magiquest_t {
uint64_t llword;
struct {
uint16_t magnitude;
uint32_t wand_id;
uint8_t StartBits; // first 8 MSB start bits are zero.
uint8_t HighByte; // just to pad the struct out to 64 bits so we can union with llword
} cmd;
};
#endif // !defined (DOXYGEN)
#define MAGIQUEST_MAGNITUDE_BITS 16 // magiquest_t.cmd.magnitude
#define MAGIQUEST_WAND_ID_BITS 32 // magiquest_t.cmd.wand_id
#define MAGIQUEST_START_BITS 8 // magiquest_t.cmd.StartBits
#define MAGIQUEST_PERIOD 1150 // Time for a full MagiQuest "bit" (1100 - 1200 usec)
#define MAGIQUEST_BITS (MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_WAND_ID_BITS) // 48 Size of the command without the start bits
// The maximum size of a packet is the sum of all 3 expected fields * 2
#define MAGIQUEST_PACKET_SIZE (MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) // 56
/*
* 0 = 25% mark & 75% space across 1 period
* 1150 * 0.25 = 288 usec mark
* 1150 - 288 = 862 usec space
* 1 = 50% mark & 50% space across 1 period
* 1150 * 0.5 = 575 usec mark
* 1150 - 575 = 575 usec space
*/
#define MAGIQUEST_UNIT (MAGIQUEST_PERIOD / 4)
#define MAGIQUEST_ONE_MARK (2 * MAGIQUEST_UNIT) // 576
#define MAGIQUEST_ONE_SPACE (2 * MAGIQUEST_UNIT) // 576
#define MAGIQUEST_ZERO_MARK MAGIQUEST_UNIT
#define MAGIQUEST_ZERO_SPACE (3 * MAGIQUEST_UNIT) // 864
//+=============================================================================
//
void IRsend::sendMagiQuest(uint32_t wand_id, uint16_t magnitude) {
// Set IR carrier frequency
enableIROut(38);
// 8 start bits
sendPulseDistanceWidthData(
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, 0, 8, PROTOCOL_IS_MSB_FIRST);
// Data
sendPulseDistanceWidthData(
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, wand_id, MAGIQUEST_WAND_ID_BITS,
PROTOCOL_IS_MSB_FIRST);
sendPulseDistanceWidthData(
MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, magnitude, MAGIQUEST_MAGNITUDE_BITS,
PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
//+=============================================================================
//
/*
* decodes a 56 bit result, which is not really compatible with standard decoder layout
*/
bool IRrecv::decodeMagiQuest() {
magiquest_t data; // Somewhere to build our code
unsigned int tOffset = 1; // Skip the gap between packets
unsigned int tMark;
unsigned int tSpace;
#if defined(DEBUG)
char bitstring[(MAGIQUEST_PACKET_SIZE + 1)];
bitstring[MAGIQUEST_PACKET_SIZE] = '\0';
#endif
// Check we have the right amount of data, magnitude and ID bits and at least 2 start bits + 1 stop bit
if (decodedIRData.rawDataPtr->rawlen < (2 * (MAGIQUEST_BITS + 3))
|| decodedIRData.rawDataPtr->rawlen > (2 * (MAGIQUEST_PACKET_SIZE + 1))) {
IR_DEBUG_PRINT(F("MagiQuest: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not between 102 and 114"));
return false;
}
// Read the bits in
data.llword = 0;
while (tOffset < (unsigned int) (decodedIRData.rawDataPtr->rawlen - 1)) {
// get one mark and space pair
tMark = decodedIRData.rawDataPtr->rawbuf[tOffset++];
tSpace = decodedIRData.rawDataPtr->rawbuf[tOffset++];
IR_TRACE_PRINT(F("MagiQuest: mark="));
IR_TRACE_PRINT(tMark * MICROS_PER_TICK);
IR_TRACE_PRINT(F(" space="));
IR_TRACE_PRINTLN(tSpace * MICROS_PER_TICK);
if (matchMark(tSpace + tMark, MAGIQUEST_PERIOD)) {
if (tSpace > tMark) {
// It's a 0
data.llword <<= 1;
#if defined(DEBUG)
bitstring[(tOffset / 2) - 1] = '0';
#endif
} else {
// It's a 1
data.llword = (data.llword << 1) | 1;
#if defined(DEBUG)
bitstring[(tOffset / 2) - 1] = '1';
#endif
}
} else {
IR_DEBUG_PRINTLN(F("Mark and space does not match the constant MagiQuest period"));
return false;
}
}
IR_DEBUG_PRINTLN(bitstring);
// Success
decodedIRData.protocol = MAGIQUEST;
decodedIRData.numberOfBits = tOffset / 2;
decodedIRData.flags = IRDATA_FLAGS_EXTRA_INFO | IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.extra = data.cmd.magnitude;
decodedIRData.decodedRawData = data.cmd.wand_id;
return true;
}
#endif // _IR_MAGIQUEST_HPP

View File

@@ -0,0 +1,380 @@
/*
* ir_NEC.hpp
*
* Contains functions for receiving and sending NEC IR Protocol in "raw" and standard format with 16 or 8 bit address and 8 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_NEC_HPP
#define _IR_NEC_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
#include "LongUnion.h"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// N N EEEEE CCCC
// NN N E C
// N N N EEE C
// N NN E C
// N N EEEEE CCCC
//==============================================================================
// see: https://www.sbprojects.net/knowledge/ir/nec.php
// for Apple see https://en.wikipedia.org/wiki/Apple_Remote
// ONKYO like NEC but 16 independent command bits
// LSB first, 1 start bit + 16 bit address (or 8 bit address and 8 bit inverted address) + 8 bit command + 8 bit inverted command + 1 stop bit.
//
#define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
#define NEC_COMMAND_BITS 16 // Command and inverted command
#define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
#define NEC_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0
#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000 / 180
#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500 / 90
#define NEC_BIT_MARK NEC_UNIT
#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690 / 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0
#define NEC_ZERO_SPACE NEC_UNIT
#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
#define NEC_AVERAGE_DURATION 62000 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2,5 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
#define NEC_REPEAT_DURATION (NEC_HEADER_MARK + NEC_REPEAT_HEADER_SPACE + NEC_BIT_MARK) // 12 ms
#define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
#define NEC_REPEAT_SPACE (NEC_REPEAT_PERIOD - NEC_AVERAGE_DURATION) // 48 ms
#define APPLE_ADDRESS 0x87EE
//+=============================================================================
/*
* Send repeat
* Repeat commands should be sent in a 110 ms raster.
*/
void IRsend::sendNECRepeat() {
enableIROut(NEC_KHZ); // 38 kHz
mark(NEC_HEADER_MARK);
space(NEC_REPEAT_HEADER_SPACE);
mark(NEC_BIT_MARK);
IrReceiver.restartAfterSend();
// ledOff(); // Always end with the LED off
}
/*
* Repeat commands should be sent in a 110 ms raster.
* There is NO delay after the last sent repeat!
* https://www.sbprojects.net/knowledge/ir/nec.php
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
*/
void IRsend::sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
LongUnion tRawData;
// Address 16 bit LSB first
if ((aAddress & 0xFF00) == 0) {
// assume 8 bit address -> send 8 address bits and then 8 inverted address bits LSB first
tRawData.UByte.LowByte = aAddress;
tRawData.UByte.MidLowByte = ~tRawData.UByte.LowByte;
} else {
tRawData.UWord.LowWord = aAddress;
}
// send 8 command bits and then 8 inverted command bits LSB first
tRawData.UByte.MidHighByte = aCommand;
tRawData.UByte.HighByte = ~aCommand;
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
}
/*
* Repeat commands should be sent in a 110 ms raster.
* There is NO delay after the last sent repeat!
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
*/
void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
LongUnion tRawData;
// Address 16 bit LSB first
tRawData.UWord.LowWord = aAddress;
// Command 16 bit LSB first
tRawData.UWord.HighWord = aCommand;
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
}
/*
* Repeat commands should be sent in a 110 ms raster.
* There is NO delay after the last sent repeat!
* https://en.wikipedia.org/wiki/Apple_Remote
* https://gist.github.com/darconeous/4437f79a34e3b6441628
* @param aAddress is the DeviceId*
* @param aIsRepeat if true, send only one repeat frame without leading and trailing space
*/
void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
LongUnion tRawData;
// Address 16 bit LSB first
tRawData.UWord.LowWord = APPLE_ADDRESS;
// send Apple code and then 8 command bits LSB first
tRawData.UByte.MidHighByte = aCommand;
tRawData.UByte.HighByte = aDeviceId; // e.g. 0xD7
sendNECRaw(tRawData.ULong, aNumberOfRepeats, aIsRepeat);
}
void IRsend::sendNECRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats, bool aIsRepeat) {
if (aIsRepeat) {
sendNECRepeat();
return;
}
// Set IR carrier frequency
enableIROut(NEC_KHZ);
// Header
mark(NEC_HEADER_MARK);
space(NEC_HEADER_SPACE);
// LSB first + stop bit
sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, aRawData, NEC_BITS, PROTOCOL_IS_LSB_FIRST,
SEND_STOP_BIT);
for (uint_fast8_t i = 0; i < aNumberOfRepeats; ++i) {
// send repeat in a 110 ms raster
if (i == 0) {
delay(NEC_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
} else {
delay((NEC_REPEAT_PERIOD - NEC_REPEAT_DURATION) / MICROS_IN_ONE_MILLI);
}
// send repeat
sendNECRepeat();
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
// NECs have a repeat only 4 items long
//
/*
* First check for right data length
* Next check start bit
* Next try the decode
* Last check stop bit
*
* Decodes also Apple
*/
bool IRrecv::decodeNEC() {
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
IR_DEBUG_PRINT(F("NEC: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 68 or 4"));
return false;
}
// Check header "mark" this must be done for repeat and data
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], NEC_HEADER_MARK)) {
return false;
}
// Check for repeat - here we have another header space length
if (decodedIRData.rawDataPtr->rawlen == 4) {
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_REPEAT_HEADER_SPACE)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], NEC_BIT_MARK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
decodedIRData.address = lastDecodedAddress;
decodedIRData.command = lastDecodedCommand;
decodedIRData.protocol = lastDecodedProtocol;
return true;
}
return false;
}
// Check command header space
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("NEC: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
if (!decodePulseDistanceData(NEC_BITS, 3, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("NEC: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * NEC_BITS)], NEC_BIT_MARK)) {
IR_DEBUG_PRINT(F("NEC: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
LongUnion tValue;
tValue.ULong = decodedIRData.decodedRawData;
decodedIRData.command = tValue.UByte.MidHighByte; // 8 bit
// Address
if (tValue.UWord.LowWord == APPLE_ADDRESS) {
/*
* Apple
*/
decodedIRData.protocol = APPLE;
decodedIRData.address = tValue.UByte.HighByte;
} else {
/*
* NEC LSB first, so first sent bit is also LSB of decodedIRData.decodedRawData
*/
if (tValue.UByte.LowByte == (uint8_t) (~tValue.UByte.MidLowByte)) {
// standard 8 bit address NEC protocol
decodedIRData.address = tValue.UByte.LowByte; // first 8 bit
} else {
// extended NEC protocol
decodedIRData.address = tValue.UWord.LowWord; // first 16 bit
}
// Check for command if it is 8 bit NEC or 16 bit ONKYO
if (tValue.UByte.MidHighByte == (uint8_t) (~tValue.UByte.HighByte)) {
decodedIRData.protocol = NEC;
} else {
decodedIRData.protocol = ONKYO;
decodedIRData.command = tValue.UWord.HighWord; // 16 bit command
/*
* Old NEC plausibility check below, now it is just ONKYO :-)
*/
// IR_DEBUG_PRINT(F("NEC: "));
// IR_DEBUG_PRINT(F("Command=0x"));
// IR_DEBUG_PRINT(tValue.UByte.MidHighByte, HEX);
// IR_DEBUG_PRINT(F(" is not inverted value of 0x"));
// IR_DEBUG_PRINTLN(tValue.UByte.HighByte, HEX);
// decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
}
}
decodedIRData.numberOfBits = NEC_BITS;
return true;
}
bool IRrecv::decodeNECMSB(decode_results *aResults) {
unsigned int offset = 1; // Index in to results; Skip first space.
// Check header "mark"
if (!matchMark(aResults->rawbuf[offset], NEC_HEADER_MARK)) {
return false;
}
offset++;
// Check for repeat
if ((aResults->rawlen == 4) && matchSpace(aResults->rawbuf[offset], NEC_REPEAT_HEADER_SPACE)
&& matchMark(aResults->rawbuf[offset + 1], NEC_BIT_MARK)) {
aResults->bits = 0;
aResults->value = 0xFFFFFFFF;
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
decodedIRData.protocol = NEC;
return true;
}
// Check we have the right amount of data (32). +4 for initial gap, start bit mark and space + stop bit mark
if (aResults->rawlen != (2 * NEC_BITS) + 4) {
IR_DEBUG_PRINT(F("NEC MSB: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(aResults->rawlen);
IR_DEBUG_PRINTLN(F(" is not 68"));
return false;
}
// Check header "space"
if (!matchSpace(aResults->rawbuf[offset], NEC_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("NEC MSB: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
offset++;
if (!decodePulseDistanceData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, NEC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
IR_DEBUG_PRINT(F("NEC MSB: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(aResults->rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) {
IR_DEBUG_PRINT(F("NEC MSB: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
aResults->value = decodedIRData.decodedRawData;
aResults->bits = NEC_BITS;
aResults->decode_type = NEC;
decodedIRData.protocol = NEC;
return true;
}
/**
* 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 bit positions of each byte.
* Or write it as one binary string and reverse/mirror it.
* Example:
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.
* 0xCB340102 is binary 11001011001101000000000100000010.
* 0x40802CD3 is binary 01000000100000000010110011010011.
* If you read the first binary sequence backwards (right to left), you get the second sequence.
*/
void IRsend::sendNECMSB(uint32_t data, uint8_t nbits, bool repeat) {
// Set IR carrier frequency
enableIROut(NEC_KHZ);
if (data == 0xFFFFFFFF || repeat) {
sendNECRepeat();
return;
}
// Header
mark(NEC_HEADER_MARK);
space(NEC_HEADER_SPACE);
// Old version with MSB first Data + stop bit
sendPulseDistanceWidthData(NEC_BIT_MARK, NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_NEC_HPP

View File

@@ -0,0 +1,335 @@
/*
* @file ir_Pronto.hpp
* @brief In this file, the functions IRrecv::compensateAndPrintPronto and IRsend::sendPronto are defined.
*
* See http://www.harctoolbox.org/Glossary.html#ProntoSemantics
* Pronto database http://www.remotecentral.com/search.htm
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020 Bengt Martensson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_PRONTO_HPP
#define _IR_PRONTO_HPP
// The first number, here 0000, denotes the type of the signal. 0000 denotes a raw IR signal with modulation,
// The second number, here 006C, denotes a frequency code
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//! @cond
// DO NOT EXPORT from this file
static const uint16_t learnedToken = 0x0000U;
static const uint16_t learnedNonModulatedToken = 0x0100U;
static const unsigned int bitsInHexadecimal = 4U;
static const unsigned int digitsInProntoNumber = 4U;
static const unsigned int numbersInPreamble = 4U;
static const unsigned int hexMask = 0xFU;
static const uint32_t referenceFrequency = 4145146UL;
static const uint16_t fallbackFrequency = 64767U; // To use with frequency = 0;
static const uint32_t microsecondsInSeconds = 1000000UL;
static const uint16_t PRONTO_DEFAULT_GAP = 45000;
//! @endcond
static unsigned int toFrequencyKHz(uint16_t code) {
return ((referenceFrequency / code) + 500) / 1000;
}
/*
* Parse the string given as Pronto Hex, and send it a number of times given as argument.
*/
void IRsend::sendPronto(const uint16_t *data, unsigned int length, uint_fast8_t aNumberOfRepeats) {
unsigned int timebase = (microsecondsInSeconds * data[1] + referenceFrequency / 2) / referenceFrequency;
unsigned int khz;
switch (data[0]) {
case learnedToken: // normal, "learned"
khz = toFrequencyKHz(data[1]);
break;
case learnedNonModulatedToken: // non-demodulated, "learned"
khz = 0U;
break;
default:
return; // There are other types, but they are not handled yet.
}
unsigned int intros = 2 * data[2];
unsigned int repeats = 2 * data[3];
IR_DEBUG_PRINT(F("sendPronto intros="));
IR_DEBUG_PRINT(intros);
IR_DEBUG_PRINT(F(" repeats="));
IR_DEBUG_PRINTLN(repeats);
if (numbersInPreamble + intros + repeats != length) { // inconsistent sizes
return;
}
/*
* Generate a new microseconds timing array for sendRaw.
* If recorded by IRremote, intro contains the whole IR data and repeat is empty
*/
uint16_t durations[intros + repeats];
for (unsigned int i = 0; i < intros + repeats; i++) {
uint32_t duration = ((uint32_t) data[i + numbersInPreamble]) * timebase;
durations[i] = (unsigned int) ((duration <= UINT16_MAX) ? duration : UINT16_MAX);
}
/*
* Send the intro. intros is even.
* Do not send the trailing space here, send it if repeats are requested
*/
if (intros >= 2) {
sendRaw(durations, intros - 1, khz);
}
if (repeats == 0 || aNumberOfRepeats == 0) {
// only send intro once
return;
}
/*
* Now send the trailing space/gap of the intro and all the repeats
*/
if (intros >= 2) {
delay(durations[intros - 1] / MICROS_IN_ONE_MILLI); // equivalent to space(durations[intros - 1]); but allow bigger values for the gap
}
for (unsigned int i = 0; i < aNumberOfRepeats; i++) {
sendRaw(durations + intros, repeats - 1, khz);
if ((i + 1) < aNumberOfRepeats) { // skip last trailing space/gap, see above
delay(durations[intros + repeats - 1] / MICROS_IN_ONE_MILLI);
}
}
}
/**
* Parse the string given as Pronto Hex, and send it a number of times given
* as the second argument. Thereby the division of the Pronto Hex into
* an intro-sequence and a repeat sequence is taken into account:
* First the intro sequence is sent, then the repeat sequence is sent times-1 times.
* However, if the intro sequence is empty, the repeat sequence is sent times times.
* <a href="http://www.harctoolbox.org/Glossary.html#ProntoSemantics">Reference</a>.
*
* Note: Using this function is very wasteful for the memory consumption on
* a small board.
* Normally it is a much better idea to use a tool like e.g. IrScrutinizer
* to transform Pronto type signals offline
* to a more memory efficient format.
*
* @param str C type string (null terminated) containing a Pronto Hex representation.
* @param aNumberOfRepeats Number of times to send the signal.
*/
void IRsend::sendPronto(const char *str, uint_fast8_t aNumberOfRepeats) {
size_t len = strlen(str) / (digitsInProntoNumber + 1) + 1;
uint16_t data[len];
const char *p = str;
char *endptr[1];
for (unsigned int i = 0; i < len; i++) {
long x = strtol(p, endptr, 16);
if (x == 0 && i >= numbersInPreamble) {
// Alignment error?, bail immediately (often right result).
len = i;
break;
}
data[i] = static_cast<uint16_t>(x); // If input is conforming, there can be no overflow!
p = *endptr;
}
sendPronto(data, len, aNumberOfRepeats);
}
#if defined(__AVR__)
/**
* Version of sendPronto that reads from PROGMEM, saving RAM memory.
* @param str pronto C type string (null terminated) containing a Pronto Hex representation.
* @param aNumberOfRepeats Number of times to send the signal.
*/
//far pointer (? for ATMega2560 etc.)
void IRsend::sendPronto_PF(uint_farptr_t str, uint_fast8_t aNumberOfRepeats) {
size_t len = strlen_PF(str);
char work[len + 1];
strncpy_PF(work, str, len);
sendPronto(work, aNumberOfRepeats);
}
//standard pointer
void IRsend::sendPronto_P(const char *str, uint_fast8_t aNumberOfRepeats) {
size_t len = strlen_P(str);
char work[len + 1];
strncpy_P(work, str, len);
sendPronto(work, aNumberOfRepeats);
}
#endif
void IRsend::sendPronto(const __FlashStringHelper *str, uint_fast8_t aNumberOfRepeats) {
size_t len = strlen_P(reinterpret_cast<const char*>(str));
char work[len + 1];
strncpy_P(work, reinterpret_cast<const char*>(str), len);
return sendPronto(work, aNumberOfRepeats);
}
static uint16_t effectiveFrequency(uint16_t frequency) {
return frequency > 0 ? frequency : fallbackFrequency;
}
static uint16_t toTimebase(uint16_t frequency) {
return microsecondsInSeconds / effectiveFrequency(frequency);
}
static uint16_t toFrequencyCode(uint16_t frequency) {
return referenceFrequency / effectiveFrequency(frequency);
}
static char hexDigit(unsigned int x) {
return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10)));
}
static void dumpDigit(Print *aSerial, unsigned int number) {
aSerial->print(hexDigit(number));
}
static void dumpNumber(Print *aSerial, uint16_t number) {
for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
dumpDigit(aSerial, (number >> shifts) & hexMask);
}
aSerial->print(' ');
}
static void dumpDuration(Print *aSerial, uint32_t duration, uint16_t timebase) {
dumpNumber(aSerial, (duration + timebase / 2) / timebase);
}
/*
* Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
*/
static void compensateAndDumpSequence(Print *aSerial, const volatile unsigned int *data, size_t length, uint16_t timebase) {
for (size_t i = 0; i < length; i++) {
uint32_t tDuration = data[i] * MICROS_PER_TICK;
if (i & 1) {
// Mark
tDuration -= getMarkExcessMicros();
} else {
tDuration += getMarkExcessMicros();
}
dumpDuration(aSerial, tDuration, timebase);
}
// append a gap
dumpDuration(aSerial, PRONTO_DEFAULT_GAP, timebase);
}
/**
* Print the result (second argument) as Pronto Hex on the Print supplied as argument.
* Used in the ReceiveDump example.
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
* @param aFrequencyHertz Modulation frequency in Hz. Often 38000Hz.
*/
void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int aFrequencyHertz) {
aSerial->println(F("Pronto Hex as string"));
aSerial->print(F("char prontoData[] = \""));
dumpNumber(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken);
dumpNumber(aSerial, toFrequencyCode(aFrequencyHertz));
dumpNumber(aSerial, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
dumpNumber(aSerial, 0);
unsigned int timebase = toTimebase(aFrequencyHertz);
compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, timebase); // skip leading space
aSerial->println("\";");
}
/*
* Functions for dumping Pronto to a String. This is not very time and space efficient
* and can lead to resource problems especially on small processors like AVR's
*/
static bool dumpDigit(String *aString, unsigned int number) {
aString->concat(hexDigit(number));
return number;
}
static size_t dumpNumber(String *aString, uint16_t number) {
size_t size = 0;
for (unsigned int i = 0; i < digitsInProntoNumber; i++) {
unsigned int shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i);
size += dumpDigit(aString, (number >> shifts) & hexMask);
}
aString->concat(' ');
size++;
return size;
}
/*
* Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
*/
static size_t dumpDuration(String *aString, uint32_t duration, uint16_t timebase) {
return dumpNumber(aString, (duration + timebase / 2) / timebase);
}
static size_t compensateAndDumpSequence(String *aString, const volatile unsigned int *data, size_t length, uint16_t timebase) {
size_t size = 0;
for (size_t i = 0; i < length; i++) {
uint32_t tDuration = data[i] * MICROS_PER_TICK;
if (i & 1) {
// Mark
tDuration -= getMarkExcessMicros();
} else {
tDuration += getMarkExcessMicros();
}
size += dumpDuration(aString, tDuration, timebase);
}
// append minimum gap
size += dumpDuration(aString, PRONTO_DEFAULT_GAP, timebase);
return size;
}
/*
* Writes Pronto HEX to a String object.
* Returns the amount of characters added to the string.(360 characters for a NEC code!)
*/
size_t IRrecv::compensateAndStorePronto(String *aString, unsigned int frequency) {
size_t size = 0;
unsigned int timebase = toTimebase(frequency);
size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken);
size += dumpNumber(aString, toFrequencyCode(frequency));
size += dumpNumber(aString, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
size += dumpNumber(aString, 0);
size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1,
timebase); // skip leading space
return size;
}
/** @}*/
#endif // _IR_PRONTO_HPP

View File

@@ -0,0 +1,559 @@
/*
* ir_RC5_RC6.hpp
*
* Contains functions for receiving and sending RC5, RC5X Protocols
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_RC5_RC6_HPP
#define _IR_RC5_RC6_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
//#define TRACE // Activate this for more debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
#include "LongUnion.h"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
bool sLastSendToggleValue = false;
//uint8_t sLastReceiveToggleValue = 3; // 3 -> start value
//==============================================================================
// RRRR CCCC 55555
// R R C 5
// RRRR C 5555
// R R C 5
// R R CCCC 5555
//==============================================================================
//
// see: https://www.sbprojects.net/knowledge/ir/rc5.php
// https://en.wikipedia.org/wiki/Manchester_code
// mark->space => 0
// space->mark => 1
// MSB first 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command (6 bit command plus one field bit for RC5X), no stop bit
// duty factor is 25%,
//
#define RC5_ADDRESS_BITS 5
#define RC5_COMMAND_BITS 6
#define RC5_COMMAND_FIELD_BIT 1
#define RC5_TOGGLE_BIT 1
#define RC5_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS) // 13
#define RC5_UNIT 889 // 32 periods of 36 kHz (888.8888)
#define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7
#define RC5_DURATION (15L * RC5_UNIT) // 13335
#define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792
#define RC5_REPEAT_SPACE (RC5_REPEAT_PERIOD - RC5_DURATION) // 100 ms
/**
* @param aCommand If aCommand is >=64 then we switch automatically to RC5X
*/
void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
// Set IR carrier frequency
enableIROut(RC5_RC6_KHZ);
uint16_t tIRData = ((aAddress & 0x1F) << RC5_COMMAND_BITS);
if (aCommand < 0x40) {
// set field bit to lower field / set inverted upper command bit
tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
} else {
// let field bit zero
aCommand &= 0x3F;
}
tIRData |= aCommand;
if (aEnableAutomaticToggle) {
if (sLastSendToggleValue == 0) {
sLastSendToggleValue = 1;
// set toggled bit
tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
} else {
sLastSendToggleValue = 0;
}
}
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// start bit is sent by sendBiphaseData
sendBiphaseData(RC5_UNIT, tIRData, RC5_BITS);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(RC5_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
/**
* Try to decode data as RC5 protocol
* _ _ _ _ _ _ _ _ _ _ _ _ _
* Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of each data bit period
* _ _ - Mark
* 2 Start bits for RC5 _____| |_| ... - Data starts with a space->mark bit
* - Space
* _
* 1 Start bit for RC5X _____| ...
*
*/
bool IRrecv::decodeRC5() {
uint8_t tBitIndex;
uint32_t tDecodedRawData = 0;
// Set Biphase decoding start values
initBiphaselevel(1, RC5_UNIT); // Skip gap space
// Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark.
if (decodedIRData.rawDataPtr->rawlen < MIN_RC5_MARKS + 2 && decodedIRData.rawDataPtr->rawlen > ((2 * RC5_BITS) + 2)) {
// no debug output, since this check is mainly to determine the received protocol
IR_DEBUG_PRINT(F("RC5: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not between 11 and 26"));
return false;
}
// Check start bit, the first space is included in the gap
if (getBiphaselevel() != MARK) {
IR_DEBUG_PRINT(F("RC5: "));
IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
return false;
}
/*
* Get data bits - MSB first
*/
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
uint8_t tStartLevel = getBiphaselevel();
uint8_t tEndLevel = getBiphaselevel();
if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
// we have a space to mark transition here
tDecodedRawData = (tDecodedRawData << 1) | 1;
} else if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
// we have a mark to space transition here
tDecodedRawData = (tDecodedRawData << 1) | 0;
} else {
// IR_TRACE_PRINT since I saw this too often
IR_DEBUG_PRINT(F("RC5: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
}
// Success
decodedIRData.numberOfBits = tBitIndex; // must be RC5_BITS
LongUnion tValue;
tValue.ULong = tDecodedRawData;
decodedIRData.decodedRawData = tDecodedRawData;
decodedIRData.command = tValue.UByte.LowByte & 0x3F;
decodedIRData.address = (tValue.UWord.LowWord >> RC5_COMMAND_BITS) & 0x1F;
// Get the inverted 7. command bit for RC5X, the inverted value is always 1 for RC5 and serves as a second start bit.
if ((tValue.UWord.LowWord & (1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS))) == 0) {
decodedIRData.command += 0x40;
}
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
if (tValue.UByte.MidLowByte & 0x8) {
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
}
// check for repeat
if (decodedIRData.rawDataPtr->rawbuf[0] < (RC5_REPEAT_PERIOD / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
}
decodedIRData.protocol = RC5;
return true;
}
//+=============================================================================
// RRRR CCCC 6666
// R R C 6
// RRRR C 6666
// R R C 6 6
// R R CCCC 666
//
//
// mark->space => 1
// space->mark => 0
// https://www.sbprojects.net/knowledge/ir/rc6.php
// https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A
// https://en.wikipedia.org/wiki/Manchester_code
#define MIN_RC6_SAMPLES 1
#define RC6_RPT_LENGTH 46000
#define RC6_LEADING_BIT 1
#define RC6_MODE_BITS 3 // never seen others than all 0 for Philips TV
#define RC6_TOGGLE_BIT 1 // toggles at every key press. Can be used to distinguish repeats from 2 key presses.
#define RC6_ADDRESS_BITS 8
#define RC6_COMMAND_BITS 8
#define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 13
#define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444)
#define RC6_HEADER_MARK (6 * RC6_UNIT) // 2666
#define RC6_HEADER_SPACE (2 * RC6_UNIT) // 889
#define RC6_TRAILING_SPACE (6 * RC6_UNIT) // 2666
#define MIN_RC6_MARKS 4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2) // 12, 4 are for preamble
#define RC6_REPEAT_SPACE 107000 // just a guess but > 2.666ms
/**
* Main RC6 send function
*/
void IRsend::sendRC6(uint32_t aRawData, uint8_t aNumberOfBitsToSend) {
// Set IR carrier frequency
enableIROut(RC5_RC6_KHZ);
// Header
mark(RC6_HEADER_MARK);
space(RC6_HEADER_SPACE);
// Start bit
mark(RC6_UNIT);
space(RC6_UNIT);
// Data MSB first
uint32_t mask = 1UL << (aNumberOfBitsToSend - 1);
for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
// The fourth bit we send is the "double width toggle bit"
unsigned int t = (i == 4) ? (RC6_UNIT * 2) : (RC6_UNIT);
if (aRawData & mask) {
mark(t);
space(t);
} else {
space(t);
mark(t);
}
}
IrReceiver.restartAfterSend();
}
/**
* Send RC6 64 bit raw data
* We do not wait for the minimal trailing space of 2666 us
*/
void IRsend::sendRC6(uint64_t data, uint8_t nbits) {
// Set IR carrier frequency
enableIROut(RC5_RC6_KHZ);
// Header
mark(RC6_HEADER_MARK);
space(RC6_HEADER_SPACE);
// Start bit
mark(RC6_UNIT);
space(RC6_UNIT);
// Data MSB first
uint64_t mask = 1ULL << (nbits - 1);
for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
// The fourth bit we send is the "double width toggle bit"
unsigned int t = (i == 4) ? (RC6_UNIT * 2) : (RC6_UNIT);
if (data & mask) {
mark(t);
space(t);
} else {
space(t);
mark(t);
}
}
IrReceiver.restartAfterSend();
}
/**
* Assemble raw data for RC6 from parameters and toggle state and send
* We do not wait for the minimal trailing space of 2666 us
* @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable.
*/
void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
LongUnion tIRRawData;
tIRRawData.UByte.LowByte = aCommand;
tIRRawData.UByte.MidLowByte = aAddress;
tIRRawData.UWord.HighWord = 0; // must clear high word
if (aEnableAutomaticToggle) {
if (sLastSendToggleValue == 0) {
sLastSendToggleValue = 1;
// set toggled bit
IR_DEBUG_PRINT(F("Set Toggle "));
tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0
} else {
sLastSendToggleValue = 0;
}
}
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINT(F("sLastSendToggleValue="));
IR_DEBUG_PRINT(sLastSendToggleValue);
IR_DEBUG_PRINT(F(" RawData="));
IR_DEBUG_PRINTLN(tIRRawData.ULong, HEX);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// start and leading bits are sent by sendRC6
sendRC6(tIRRawData.ULong, RC6_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(RC6_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
}
/**
* Try to decode data as RC6 protocol
*/
bool IRrecv::decodeRC6() {
uint8_t tBitIndex;
uint32_t tDecodedRawData = 0;
// Check we have the right amount of data (). The +3 for initial gap, start bit mark and space
if (decodedIRData.rawDataPtr->rawlen < MIN_RC6_MARKS + 3 && decodedIRData.rawDataPtr->rawlen > ((2 * RC6_BITS) + 3)) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not between 15 and 45"));
return false;
}
// Check header "mark" and "space", this must be done for repeat and data
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], RC6_HEADER_MARK)
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], RC6_HEADER_SPACE)) {
// no debug output, since this check is mainly to determine the received protocol
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
return false;
}
// Set Biphase decoding start values
initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark + space
// Process first bit, which is known to be a 1 (mark->space)
if (getBiphaselevel() != MARK) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
return false;
}
if (getBiphaselevel() != SPACE) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("second getBiphaselevel() is not SPACE"));
return false;
}
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
uint8_t tStartLevel; // start level of coded bit
uint8_t tEndLevel; // end level of coded bit
tStartLevel = getBiphaselevel();
if (tBitIndex == 3) {
// Toggle bit is double wide; make sure second half is equal first half
if (tStartLevel != getBiphaselevel()) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("Toggle mark or space length is wrong"));
return false;
}
}
tEndLevel = getBiphaselevel();
if (tBitIndex == 3) {
// Toggle bit is double wide; make sure second half matches
if (tEndLevel != getBiphaselevel()) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("Toggle mark or space length is wrong"));
return false;
}
}
/*
* Determine tDecodedRawData bit value by checking the transition type
*/
if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
// we have a mark to space transition here
tDecodedRawData = (tDecodedRawData << 1) | 1; // inverted compared to RC5
} else if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
// we have a space to mark transition here
tDecodedRawData = (tDecodedRawData << 1) | 0;
} else {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
// we have no transition here or one level is -1 -> error
return false; // Error
}
}
// Success
decodedIRData.numberOfBits = tBitIndex;
LongUnion tValue;
tValue.ULong = tDecodedRawData;
decodedIRData.decodedRawData = tDecodedRawData;
if (tBitIndex < 36) {
// RC6
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.command = tValue.UByte.LowByte;
decodedIRData.address = tValue.UByte.MidLowByte;
// Check for toggle flag
if ((tValue.UByte.MidHighByte & 1) != 0) {
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
}
} else {
// RC6A
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
if ((tValue.UByte.MidLowByte & 0x80) != 0) {
decodedIRData.flags = IRDATA_TOGGLE_BIT_MASK | IRDATA_FLAGS_IS_MSB_FIRST;
}
tValue.UByte.MidLowByte &= 0x87F; // mask toggle bit
decodedIRData.command = tValue.UByte.LowByte;
decodedIRData.address = tValue.UByte.MidLowByte;
}
// check for repeat, do not check toggle bit yet
if (decodedIRData.rawDataPtr->rawbuf[0] < ((RC6_REPEAT_SPACE + (RC6_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
}
decodedIRData.protocol = RC6;
return true;
}
/**
* Old version with 32 bit data
*/
void IRsend::sendRC5(uint32_t data, uint8_t nbits) {
// Set IR carrier frequency
enableIROut(RC5_RC6_KHZ);
// Start
mark(RC5_UNIT);
space(RC5_UNIT);
mark(RC5_UNIT);
// Data - Biphase code MSB first
for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
if (data & mask) {
space(RC5_UNIT); // 1 is space, then mark
mark(RC5_UNIT);
} else {
mark(RC5_UNIT);
space(RC5_UNIT);
}
}
IrReceiver.restartAfterSend();
}
/*
* Not longer required, use sendRC5 instead
*/
void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) {
// Set IR carrier frequency
enableIROut(RC5_RC6_KHZ);
uint8_t addressBits = 5;
uint8_t commandBits = 7;
// unsigned long nbits = addressBits + commandBits;
// Start
mark(RC5_UNIT);
// Bit #6 of the command part, but inverted!
uint8_t cmdBit6 = (1UL << (commandBits - 1)) & cmd;
if (cmdBit6) {
// Inverted (1 -> 0 = mark-to-space)
mark(RC5_UNIT);
space(RC5_UNIT);
} else {
space(RC5_UNIT);
mark(RC5_UNIT);
}
commandBits--;
// Toggle bit
static int toggleBit = 1;
if (toggle) {
if (toggleBit == 0) {
toggleBit = 1;
} else {
toggleBit = 0;
}
}
if (toggleBit) {
space(RC5_UNIT);
mark(RC5_UNIT);
} else {
mark(RC5_UNIT);
space(RC5_UNIT);
}
// Address
for (uint_fast8_t mask = 1UL << (addressBits - 1); mask; mask >>= 1) {
if (addr & mask) {
space(RC5_UNIT); // 1 is space, then mark
mark(RC5_UNIT);
} else {
mark(RC5_UNIT);
space(RC5_UNIT);
}
}
// Command
for (uint_fast8_t mask = 1UL << (commandBits - 1); mask; mask >>= 1) {
if (cmd & mask) {
space(RC5_UNIT); // 1 is space, then mark
mark(RC5_UNIT);
} else {
mark(RC5_UNIT);
space(RC5_UNIT);
}
}
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_RC5_RC6_HPP

View File

@@ -0,0 +1,270 @@
/*
* ir_Samsung.hpp
*
* Contains functions for receiving and sending Samsung IR Protocol in "raw" and standard format with 16 bit address and 16 or 32 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2021 Darryl Smith, 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 CONSAMSUNGTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_SAMSUNG_HPP
#define _IR_SAMSUNG_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
#include "LongUnion.h"
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// SSSS AAA MMM SSSS U U N N GGGG
// S A A M M M S U U NN N G
// SSS AAAAA M M M SSS U U N N N G GG
// S A A M M S U U N NN G G
// SSSS A A M M SSSS UUU N N GGG
//==============================================================================
// see http://www.hifi-remote.com/wiki/index.php?title=DecodeIR#Samsung
// https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG32
// LSB first, 1 start bit + 16 bit address + 16,32,20 bit data + 1 stop bit.
// On my Samsung remote they are plain repeats of the complete frame.
#define SAMSUNG_ADDRESS_BITS 16
#define SAMSUNG_COMMAND16_BITS 16
#define SAMSUNG_COMMAND32_BITS 32
#define SAMSUNG_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND16_BITS)
#define SAMSUNG48_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND32_BITS)
#define SAMSUNG_UNIT 553 // 21 periods of 38 kHz (552,631) TICKS_LOW = 8.253 TICKS_HIGH = 14.825
#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4400
#define SAMSUNG_HEADER_SPACE (8 * SAMSUNG_UNIT) // 4400
#define SAMSUNG_BIT_MARK SAMSUNG_UNIT
#define SAMSUNG_ONE_SPACE (3 * SAMSUNG_UNIT) // 1650 TICKS_LOW = 24.62 TICKS_HIGH = 42.25
#define SAMSUNG_ZERO_SPACE SAMSUNG_UNIT
#define SAMSUNG_AVERAGE_DURATION 55000 // SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones
#define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
/**
* Please note me (armin.arduino@gmail.com) if you ever see this special repeat in the wild
* Send repeat
* Repeat commands should be sent in a 110 ms raster.
*/
void IRsend::sendSamsungRepeat() {
enableIROut(SAMSUNG_KHZ); // 38 kHz
mark(SAMSUNG_HEADER_MARK);
space(SAMSUNG_HEADER_SPACE);
mark(SAMSUNG_BIT_MARK);
space(SAMSUNG_ZERO_SPACE);
mark(SAMSUNG_BIT_MARK);
IrReceiver.restartAfterSend();
}
void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(SAMSUNG_KHZ);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
// Header
mark(SAMSUNG_HEADER_MARK);
space(SAMSUNG_HEADER_SPACE);
// Address
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, aAddress,
SAMSUNG_ADDRESS_BITS, PROTOCOL_IS_LSB_FIRST);
// Command
// send 8 command bits and then 8 inverted command bits LSB first
aCommand = aCommand & 0xFF;
aCommand = ((~aCommand) << 8) | aCommand;
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, aCommand,
SAMSUNG_COMMAND16_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeat in a 110 ms raster
while (millis() - tStartOfFrameMillis < (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI)) {
delay(1);
}
}
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
bool IRrecv::decodeSamsung() {
// Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG_BITS) + 4)
&& decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG48_BITS) + 4)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 68 or 100"));
return false;
}
// Check header "mark" + "space"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SAMSUNG_HEADER_MARK)
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SAMSUNG_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
return false;
}
if (decodedIRData.rawDataPtr->rawlen == (2 * SAMSUNG48_BITS) + 4) {
/*
* Samsung48
*/
// decode address
if (!decodePulseDistanceData(SAMSUNG_ADDRESS_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
decodedIRData.address = decodedIRData.decodedRawData;
// decode 32 bit command
if (!decodePulseDistanceData(SAMSUNG_COMMAND32_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
LongUnion tValue;
tValue.ULong = decodedIRData.decodedRawData;
// receive 2 * (8 bits then 8 inverted bits) LSB first
if (tValue.UByte.HighByte != (uint8_t) (~tValue.UByte.MidHighByte)
&& tValue.UByte.MidLowByte != (uint8_t) (~tValue.UByte.LowByte)) {
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST;
}
decodedIRData.command = tValue.UByte.HighByte << 8 | tValue.UByte.MidLowByte;
decodedIRData.numberOfBits = SAMSUNG48_BITS;
} else {
/*
* Samsung32
*/
if (!decodePulseDistanceData(SAMSUNG_BITS, 3, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
LongUnion tValue;
tValue.ULong = decodedIRData.decodedRawData;
decodedIRData.address = tValue.UWord.LowWord;
if (tValue.UByte.MidHighByte == (uint8_t) (~tValue.UByte.HighByte)) {
// 8 bit command protocol
decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit
} else {
// 16 bit command protocol
decodedIRData.command = tValue.UWord.HighWord; // first 16 bit
}
decodedIRData.numberOfBits = SAMSUNG_BITS;
}
// check for repeat
if (decodedIRData.rawDataPtr->rawbuf[0] < (SAMSUNG_REPEAT_PERIOD / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
}
decodedIRData.protocol = SAMSUNG;
return true;
}
bool IRrecv::decodeSAMSUNG(decode_results *aResults) {
unsigned int offset = 1; // Skip first space
// Initial mark
if (!matchMark(aResults->rawbuf[offset], SAMSUNG_HEADER_MARK)) {
return false;
}
offset++;
// Check for repeat -- like a NEC repeat
if ((aResults->rawlen == 4) && matchSpace(aResults->rawbuf[offset], 2250)
&& matchMark(aResults->rawbuf[offset + 1], SAMSUNG_BIT_MARK)) {
aResults->bits = 0;
aResults->value = 0xFFFFFFFF;
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
decodedIRData.protocol = SAMSUNG;
return true;
}
if (aResults->rawlen < (2 * SAMSUNG_BITS) + 4) {
return false;
}
// Initial space
if (!matchSpace(aResults->rawbuf[offset], SAMSUNG_HEADER_SPACE)) {
return false;
}
offset++;
if (!decodePulseDistanceData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE,
PROTOCOL_IS_MSB_FIRST)) {
return false;
}
// Success
aResults->value = decodedIRData.decodedRawData;
aResults->bits = SAMSUNG_BITS;
aResults->decode_type = SAMSUNG;
decodedIRData.protocol = SAMSUNG;
return true;
}
// Old version with MSB first
void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(SAMSUNG_KHZ);
// Header
mark(SAMSUNG_HEADER_MARK);
space(SAMSUNG_HEADER_SPACE);
// Old version with MSB first Data + stop bit
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST, SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_SAMSUNG_HPP

View File

@@ -0,0 +1,230 @@
/*
* ir_Sony.hpp
*
* Contains functions for receiving and sending SIRCS/Sony IR Protocol in "raw" and standard format with 5 bit address 7 bit command
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_SONY_HPP
#define _IR_SONY_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// SSSS OOO N N Y Y
// S O O NN N Y Y
// SSS O O N N N Y
// S O O N NN Y
// SSSS OOO N N Y
//==============================================================================
// see https://www.sbprojects.net/knowledge/ir/sirc.php
// Here http://picprojects.org.uk/projects/sirc/ it is claimed, that many Sony remotes repeat each frame a minimum of 3 times
// LSB first, start bit + 7 command + 5 to 13 address, no stop bit
//
#define SONY_ADDRESS_BITS 5
#define SONY_COMMAND_BITS 7
#define SONY_EXTRA_BITS 8
#define SONY_BITS_MIN (SONY_COMMAND_BITS + SONY_ADDRESS_BITS) // 12 bits
#define SONY_BITS_15 (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + 3) // 15 bits
#define SONY_BITS_MAX (SONY_COMMAND_BITS + SONY_ADDRESS_BITS + SONY_EXTRA_BITS) // 20 bits == SIRCS_20_PROTOCOL
#define SONY_UNIT 600 // 24 periods of 40kHz
#define SONY_HEADER_MARK (4 * SONY_UNIT) // 2400
#define SONY_ONE_MARK (2 * SONY_UNIT) // 1200
#define SONY_ZERO_MARK SONY_UNIT
#define SONY_SPACE SONY_UNIT
#define SONY_AVERAGE_DURATION 21000 // SONY_HEADER_MARK + SONY_SPACE + 12 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones
#define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down.
#define SONY_REPEAT_SPACE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION) // 24 ms
/*
* Repeat commands should be sent in a 45 ms raster.
* There is NO delay after the last sent command / repeat!
* @param numberOfBits if == 20 send 13 address bits otherwise only 5 address bits
*/
void IRsend::sendSony(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint8_t numberOfBits) {
// Set IR carrier frequency
enableIROut(SONY_KHZ); // 40 kHz
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Header
mark(SONY_HEADER_MARK);
space(SONY_SPACE);
// send 7 command bits LSB first
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, aCommand, SONY_COMMAND_BITS,
PROTOCOL_IS_LSB_FIRST);
// send 5, 8, 13 address bits LSB first
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, aAddress,
(numberOfBits - SONY_COMMAND_BITS), PROTOCOL_IS_LSB_FIRST);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a 45 ms raster
delay(SONY_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
bool IRrecv::decodeSony() {
// Check header "mark"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SONY_HEADER_MARK)) {
return false;
}
// Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42
if (decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MAX) + 2
&& decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_15) + 2) {
// ??? IR_TRACE_PRINT since I saw this too often
IR_DEBUG_PRINT(F("Sony: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINTLN(F(" is not 12, 15 or 20"));
return false;
}
// Check header "space"
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SONY_SPACE)) {
IR_DEBUG_PRINT(F("Sony: "));
IR_DEBUG_PRINTLN(F("Header space length is wrong"));
return false;
}
if (!decodePulseWidthData((decodedIRData.rawDataPtr->rawlen - 1) / 2, 3, SONY_ONE_MARK, SONY_ZERO_MARK, SONY_SPACE,
PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Sony: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
uint8_t tCommand = decodedIRData.decodedRawData & 0x7F; // first 7 bits
uint16_t tAddress = decodedIRData.decodedRawData >> 7; // next 5 or 8 or 13 bits
/*
* Check for repeat
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < (SONY_REPEAT_PERIOD / MICROS_PER_TICK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
}
decodedIRData.command = tCommand;
decodedIRData.address = tAddress;
decodedIRData.numberOfBits = (decodedIRData.rawDataPtr->rawlen - 1) / 2;
decodedIRData.protocol = SONY;
return true;
}
#define SONY_DOUBLE_SPACE_USECS 500 // usually see 713 - not using ticks as get number wrap around
bool IRrecv::decodeSonyMSB(decode_results *aResults) {
long data = 0;
uint8_t bits = 0;
unsigned int offset = 0; // Dont skip first space, check its size
if (aResults->rawlen < (2 * SONY_BITS_MIN) + 2) {
return false;
}
// Some Sony's deliver repeats fast after first
// unfortunately can't spot difference from of repeat from two fast clicks
if (aResults->rawbuf[0] < (SONY_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) {
IR_DEBUG_PRINTLN(F("IR Gap found"));
aResults->bits = 0;
aResults->value = 0xFFFFFFFF;
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
decodedIRData.protocol = SONY;
return true;
}
offset++;
// Check header "mark"
if (!matchMark(aResults->rawbuf[offset], SONY_HEADER_MARK)) {
return false;
}
offset++;
// MSB first - Not compatible to standard, which says LSB first :-(
while (offset + 1 < aResults->rawlen) {
// First check for the constant space length, we do not have a space at the end of raw data
// we are lucky, since the start space is equal the data space.
if (!matchSpace(aResults->rawbuf[offset], SONY_SPACE)) {
return false;
}
offset++;
// bit value is determined by length of the mark
if (matchMark(aResults->rawbuf[offset], SONY_ONE_MARK)) {
data = (data << 1) | 1;
} else if (matchMark(aResults->rawbuf[offset], SONY_ZERO_MARK)) {
data = (data << 1) | 0;
} else {
return false;
}
offset++;
bits++;
}
aResults->bits = bits;
aResults->value = data;
aResults->decode_type = SONY;
decodedIRData.protocol = SONY;
return true;
}
/**
* Old version with MSB first data
*/
void IRsend::sendSony(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(SONY_KHZ);
// Header
mark(SONY_HEADER_MARK);
space(SONY_SPACE);
// Old version with MSB first Data
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
IrReceiver.restartAfterSend();
}
/** @}*/
#endif // _IR_SONY_HPP

View File

@@ -0,0 +1,218 @@
/*
Assuming the protocol we are adding is for the (imaginary) manufacturer: Shuzu
Our fantasy protocol is a standard protocol, so we can use this standard
template without too much work. Some protocols are quite unique and will require
considerably more work in this file! It is way beyond the scope of this text to
explain how to reverse engineer "unusual" IR protocols. But, unless you own an
oscilloscope, the starting point is probably to use the ReceiveDump.ino sketch and
try to spot the pattern!
Before you start, make sure the IR library is working OK:
# Open up the Arduino IDE
# Load up the ReceiveDump.ino example sketch
# Run it
# Analyze your data to have an idea, what is the header timing, the bit timing, the address, the command and the checksum of your protocol.
Now we can start to add our new protocol...
1. Copy this file to : ir_<YourProtocolName>.hpp
2. Replace all occurrences of "Shuzu" with the name of your protocol.
3. Tweak the #defines to suit your protocol.
4. If you're lucky, tweaking the #defines will make the decode and send() function
work.
You have now written the code to support your new protocol!
To integrate it into the IRremote library, you must search for "BOSEWAVE"
and add your protocol in the same way as it is already done for BOSEWAVE.
You have to change the following files:
IRSend.hpp IRsend::write(IRData *aIRSendData + uint_fast8_t aNumberOfRepeats)
IRProtocol.h Add it to decode_type_t
IRReceive.hpp IRrecv::decode() + printActiveIRProtocols(Print *aSerial) + getProtocolString(decode_type_t aProtocol)
IRremote.hpp At 3 occurrences of DECODE_XXX
IRremoteInt.h Add the declaration of the decode and send function
Now open the Arduino IDE, load up the ReceiveDump.ino sketch, and run it.
Hopefully it will compile and upload.
If it doesn't, you've done something wrong. Check your work and look carefully at the error messages.
If you get this far, I will assume you have successfully added your new protocol
At last, delete this giant instructional comment.
If you want us to include your work in the library so others may benefit
from your hard work, you have to extend the examples
IRremoteInfo, SmallReceiver, simple Receiver, SendDemo and UnitTest too
as well as the Readme.md
It is not an act, but required for completeness.
Thanks
The maintainer
*/
/*
* ir_Shuzu.cpp
*
* Contains functions for receiving and sending Shuzu IR Protocol ...
*
* Copyright (C) 2022 Shuzu Guru
* shuzu.guru@gmail.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2022 Unknown Contributor :-)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _IR_SHUZU_HPP
#define _IR_SHUZU_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
//#define SEND_SHUZU 1 // for testing
//#define DECODE_SHUZU 1 // for testing
//==============================================================================
//
//
// S H U Z U
//
//
//==============================================================================
// see: https://www....
// LSB first, 1 start bit + 16 bit address + 8 bit command + 1 stop bit.
#define SHUZU_ADDRESS_BITS 16 // 16 bit address
#define SHUZU_COMMAND_BITS 8 // Command
#define SHUZU_BITS (SHUZU_ADDRESS_BITS + SHUZU_COMMAND_BITS) // The number of bits in the protocol
#define SHUZU_UNIT 560
#define SHUZU_HEADER_MARK (16 * SHUZU_UNIT) // The length of the Header:Mark
#define SHUZU_HEADER_SPACE (8 * SHUZU_UNIT) // The length of the Header:Space
#define SHUZU_BIT_MARK SHUZU_UNIT // The length of a Bit:Mark
#define SHUZU_ONE_SPACE (3 * SHUZU_UNIT) // The length of a Bit:Space for 1's
#define SHUZU_ZERO_SPACE SHUZU_UNIT // The length of a Bit:Space for 0's
#define SHUZU_REPEAT_HEADER_SPACE (4 * SHUZU_UNIT) // 2250
#define SHUZU_REPEAT_SPACE 45000
#define SHUZU_OTHER 1234 // Other things you may need to define
//+=============================================================================
//
void IRsend::sendShuzu(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
// Set IR carrier frequency
enableIROut(38);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Header
mark(SHUZU_HEADER_MARK);
space(SHUZU_HEADER_SPACE);
// Address (device and subdevice)
sendPulseDistanceWidthData(SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, aAddress,
SHUZU_ADDRESS_BITS, PROTOCOL_IS_LSB_FIRST); // false -> LSB first
// Command + stop bit
sendPulseDistanceWidthData(SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, aCommand,
SHUZU_COMMAND_BITS, PROTOCOL_IS_LSB_FIRST, SEND_STOP_BIT); // false, true -> LSB first, stop bit
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
// send repeated command in a fixed raster
delay(SHUZU_REPEAT_SPACE / MICROS_IN_ONE_MILLI);
}
}
IrReceiver.restartAfterSend();
}
//+=============================================================================
//
/*
* First check for right data length
* Next check start bit
* Next try the decode
* Last check stop bit
*/
bool IRrecv::decodeShuzu() {
// Check we have the right amount of data (28). The +4 is for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * SHUZU_BITS) + 4) {
// no debug output, since this check is mainly to determine the received protocol
return false;
}
// Check header "space"
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], SHUZU_HEADER_MARK)
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], SHUZU_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("Shuzu: "));
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
return false;
}
// false -> LSB first
if (!decodePulseDistanceData(SHUZU_BITS, 3, SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST)) {
IR_DEBUG_PRINT(F("Shuzu: "));
IR_DEBUG_PRINTLN(F("Decode failed"));
return false;
}
// Stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * SHUZU_BITS)], SHUZU_BIT_MARK)) {
IR_DEBUG_PRINT(F("Shuzu: "));
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
uint8_t tCommand = decodedIRData.decodedRawData >> SHUZU_ADDRESS_BITS; // upper 8 bits of LSB first value
uint8_t tAddress = decodedIRData.decodedRawData & 0xFFFF; // lowest 16 bit of LSB first value
/*
* Check for repeat
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < ((SHUZU_REPEAT_SPACE + (SHUZU_REPEAT_SPACE / 4)) / MICROS_PER_TICK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
}
decodedIRData.command = tCommand;
decodedIRData.address = tAddress;
decodedIRData.numberOfBits = SHUZU_BITS;
decodedIRData.protocol = BOSEWAVE; // we have no SHUZU code
return true;
}
#endif // _IR_SHUZU_HPP

View File

@@ -0,0 +1,82 @@
#ifndef _IR_WHYNTER_HPP
#define _IR_WHYNTER_HPP
#include <Arduino.h>
//#define DEBUG // Activate this for lots of lovely debug output from this decoder.
#include "IRremoteInt.h" // evaluates the DEBUG for IR_DEBUG_PRINT
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
//==============================================================================
// W W H H Y Y N N TTTTT EEEEE RRRRR
// W W H H Y Y NN N T E R R
// W W W HHHHH Y N N N T EEE RRRR
// W W W H H Y N NN T E R R
// WWW H H Y N N T EEEEE R R
//==============================================================================
// Whynter A/C ARC-110WD added by Francesco Meschia
// see https://docs.google.com/spreadsheets/d/1dsr4Jh-nzC6xvSKGpLlPBF0NRwvlpyw-ozg8eZU813w/edit#gid=0
#define WHYNTER_BITS 32
#define WHYNTER_HEADER_MARK 2850
#define WHYNTER_HEADER_SPACE 2850
#define WHYNTER_BIT_MARK 750
#define WHYNTER_ONE_SPACE 2150
#define WHYNTER_ZERO_SPACE 750
//+=============================================================================
void IRsend::sendWhynter(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut(38);
// Start
mark(WHYNTER_BIT_MARK);
space(WHYNTER_ZERO_SPACE);
// Header
mark(WHYNTER_HEADER_MARK);
space(WHYNTER_HEADER_SPACE);
// Data + stop bit
sendPulseDistanceWidthData(WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST,
SEND_STOP_BIT);
IrReceiver.restartAfterSend();
}
//+=============================================================================
bool IRrecv::decodeWhynter() {
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != (2 * WHYNTER_BITS) + 4) {
return false;
}
// Sequence begins with a bit mark and a zero space
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], WHYNTER_BIT_MARK)
|| !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], WHYNTER_HEADER_SPACE)) {
IR_DEBUG_PRINT(F("Whynter: "));
IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
return false;
}
if (!decodePulseDistanceData(WHYNTER_BITS, 3, WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) {
return false;
}
// trailing mark / stop bit
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * WHYNTER_BITS)], WHYNTER_BIT_MARK)) {
IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
return false;
}
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.numberOfBits = WHYNTER_BITS;
decodedIRData.protocol = WHYNTER;
return true;
}
/** @}*/
#endif // _IR_WHYNTER_HPP

File diff suppressed because it is too large Load Diff