.
================================================
FILE: README.md
================================================
# [IRMP](https://github.com/IRMP-org/IRMP) - Infrared Multi Protocol Decoder + Encoder
A library enabling the sending & receiving of infra-red signals with a low memory footprint.
Supports 50 different protocols.
[](https://www.gnu.org/licenses/gpl-3.0)
[](https://github.com/IRMP-org/IRMP/releases/latest)
[](https://github.com/IRMP-org/IRMP/commits/master)
[](https://github.com/IRMP-org/IRMP/actions)

[](https://stand-with-ukraine.pp.ua)
Available as [Arduino library "IRMP"](https://www.arduinolibraries.info/libraries/irmp).
[](https://www.ardu-badge.com/IRMP)
[](https://github.com/IRMP-org/IRMP?tab=readme-ov-file#revision-history)
#### If you find this library useful, please give it a star.
🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/IRMP-org/IRMP)
# Features
- Total of 50 IR protocols supported.
- Up to 39 protocols can be enabled for receive at the same time, because some of the 50 protocols are quite similar and conflicts with each other.
- 39 protocols are available for send.
- Low memory footprint. FLASH usage in bytes: 1500 for one protocol, 4300 for 15 main and 8000 for all 39 protocols.
- RAM usage in bytes: 52, 73 and 100.
| Nano running AllProtocol example | YouTube Video | Instructable |
|-|-|-|
|  |  | [](https://www.instructables.com/id/IR-Remote-Analyzer-Receiver-With-Arduino) |
# List of protocols
` Sony SIRCS ` ` NEC + APPLE + ONKYO ` ` Samsung + Samsg32 ` ` Kaseikyo `
` JVC ` ` NEC16 + NEC42 ` ` Matsushita ` ` DENON `
` Sharp ` ` RC5 ` ` RC6 & RC6A ` ` IR60 (SDA2008) Grundig `
` Siemens Gigaset ` ` Nokia `
` BOSE ` ` Kathrein ` ` NUBERT ` ` FAN (ventilator) `
` SPEAKER (~NUBERT) ` ` Bang & Olufsen ` ` RECS80 (SAA3004) `
` RECS80EXT (SAA3008) ` ` Thomson ` ` NIKON camera `
` Netbox keyboard ` ` ORTEK (Hama) ` ` Telefunken 1560 `
` FDC3402 keyboard ` ` RC Car ` ` iRobot Roomba `
` RUWIDO ` ` T-Home ` ` A1 TV BOX ` ` LEGO Power RC `
` RCMM 12,24, or 32 ` ` LG Air Condition ` ` Samsung48 `
` Merlin ` ` Pentax ` ` S100 ` ` ACP24 ` ` TECHNICS `
` PANASONIC Beamer ` ` Mitsubishi Aircond ` ` VINCENT `
` SAMSUNG AH ` ` GREE CLIMATE ` ` RCII T+A `
` RADIO e.g. TEVION ` ` METZ `
` NEC ` ` Kaseiko ` ` Denon ` ` RC6 ` ` Samsung + Samsg32 ` were successfully tested in **interrupt mode**, but there are many protocols which **in principle cannot be decoded** in this mode.
# Features
- You may use **every pin for input or output**.
- Interrupt mode for major protocols.
- Callback after successful receive of a command.
- Support for inverted feedback LED (for send and receive feedback).
- Support for inverted IR output for LED connected to VCC.
- Unmodulated IR signal output enables direct replacment of an IR receiver circuit.
- Compatible with Arduino tone library.
- Send can also also wait for trailing space/gap.
# Restrictions
- Send IR frequency is fixed at 38 kHz.
# Minimal version
For applications only requiring NEC protocol, there is a receiver which has very **small codesize of 500 bytes and does NOT require any timer**. See the MinimalReceiver and IRDispatcherDemo example how to use it. Mapping of pins to interrupts can be found [here](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src/TinyIRReceiver.hpp#L259).
# Schematic for Arduino Uno
The VS1838B is used as receiver for all examples and tests. This module has a 120 µs on/low and a 100 µs off/high delay between received signal and output. So it shortens the mark and extends the space by 20 µs.
| IR-Receiver connection | Serial LCD connection |
|---|---|
 | 
# Supported Arduino architectures / CPU's / boards
For **ESP8266/ESP32**, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)
ATtiny and Digispark boards are tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board.
| Architecture | CPU | Board |
|-|-:|-:|
| avr | ATmega16, ATmega328P, ATmega32U4, ATtinyX5, ATtinyX7 | Uno, Nano, Leonardo, Sparkfun Pro Micro, Digispark etc. |
| megaavr | ATmega4809 | Uno WiFi Rev 2, Nano Every |
| samd | SAMD21G18A | Zero, MKR*, etc. **but not DUE, which is sam architecture** |
| esp8266 | All protocols does not fit in IRAM | all |
| esp32 | % | all |
| stm32 | STM32F1xx | BluePill |
| STM32F1 | STM32F1xx | BluePill |
| apollo3 | Ambiq Apollo3 | Sparkfun Apollo3 + Artemis |
| mbed | nRF528x | Nano 33 BLE |
| Teensiduino | all - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries) | >= Teensy 3 |
# Quick comparison of 5 Arduino IR receiving libraries
**This is a short comparison and may not be complete or correct.**
I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.
It is dated from **24.06.2022** and updated 10/2023. If you have complains about the data or request for extensions, please send a PM or open a discussion.
[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**.
| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)
**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver/TinyReceiver.ino) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
|-|-|-|-|-|-|-|
| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC + FAST | NEC + RC5 + Sony + Samsung |
| Timing method receive | Timer2 or interrupt for pin 2 or 3 | **Interrupt** | Timer2 or interrupt for pin 2 or 3 | Timer2 | **Interrupt** | **Interrupt** |
| Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay
Microseconds() | blocking wait with delay
Microseconds() | % |
| Send pins| All | All | All ? | Timer dependent | All | % |
| Decode method | OnTheFly | OnTheFly | RAM | RAM | OnTheFly | OnTheFly |
| Encode method | OnTheFly | OnTheFly | OnTheFly | OnTheFly or RAM | OnTheFly | % |
| Callback suppport | x | % | % | x | x | % |
| Repeat handling | Receive + Send (partially) | % | ? | Receive + Send | Receive + Send | Receive |
| LED feedback | x | % | x | x | Receive | % |
| FLASH usage (simple NEC example with 5 prints) | 1820
(4300 for 15 main / 8000 for all 40 protocols)
(+200 for callback)
(+80 for interrupt at pin 2+3)| 1270
(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? |
| RAM usage | 52
(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 |
| Supported platforms | **avr, megaavr, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3
(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attach
Interrupt()** | **All platforms with attach
Interrupt()** |
| Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 |
| Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 63 issues, 10 pull requests.* | Universal decoder and encoder.
Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. |
\* The Hash protocol gives you a hash as code, which may be sufficient to distinguish your keys on the remote, but may not work with some protocols like Mitsubishi
# Pin usage
You may use **every pin for input or output**, just define it like `#define IRMP_INPUT_PIN 2` and `#define IRSND_OUTPUT_PIN 3`. The PWM of the output pin is generated by software bit banging.
# Dynamic pins numbers
If you want to use pin numbers for input, output and LED feedback specified at runtime, you must define `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. See [ReceiveAndSendDynamicPins example](examples/ReceiveAndSendDynamicPins/ReceiveAndSendDynamicPins.ino).
The `irmp_init` and `irsnd_init` function then allows up to 3 parameters `uint_fast8_t aIrmpInputPin/aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow`.
Be aware, only one pin and enable flag for receive and send feedback LED is supported.
# Receiving and sending simultaneously
Receiving and sending is possible with this library, but since we use only 1 timer, receiving is inhibited while sending the IR signal.
Sending the IR signal starts with saving current timer configuration, setting the timer to the send configuration / frequency, sending the signal (and waiting for the gap after the signal) and then automatically reset the timer to its previous (receiving) configuration.
# API
### IRMP
```c++
// Init functions
void irmp_init (void);
void irmp_init(uint_fast8_t aIrmpInputPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);
void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void));
// Info function
bool irmp_IsBusy();
void irmp_print_active_protocols(Print *aSerial);
// Main check for result function used in loop()
bool irmp_get_data (IRMP_DATA *)
// Result print functions
void irmp_result_print(Print *aSerial, IRMP_DATA * aIRMPDataPtr);
void irmp_result_print(IRMP_DATA *aIRMPDataPtr);
```
### IRSND
```c++
// Init functions
void irsnd_init (void);
// 3 additional init functions if IRMP_IRSND_ALLOW_DYNAMIC_PINS is defined
void irsnd_init(uint_fast8_t aIrsndOutputPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);
// Send function - sends frame AND trailing space
bool irsnd_send_data (IRMP_DATA *, uint8_t);
// Info functions
bool irsnd_is_busy (void);
void irsnd_stop (void);
```
### IRMP and IRSND
```c++
// LED feedback function
void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed);
// Timer management functions for
void disableIRTimerInterrupt(void);
void enableIRTimerInterrupt(void);
void storeIRTimer(void);
void restoreIRTimer(void);
```
# Examples
These examples can be found in the Arduino IDE under File > Examples > Examples from Custom Libraries / IRMP.
In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.
### AllProtocols
Receives up to 40 protocols concurrently and **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).
### SimpleReceiver + SimpleSender
This examples are a good starting point.
SimpleReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/298945438795432456).
Click on the receiver while simulation is running to specify individual IR codes.
#### MinimalReceiver + MinimalSender
If **code size** matters, look at these examples.
The **MinimalReceiver** example uses the **TinyReceiver** library which can **only receive NEC and FAST codes, but does not require any timer**.
MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
Click on the receiver while simulation is running to specify individual IR codes.
### SmallReceiver
If the protocol is not NEC and code size matters, look at this example.
MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299034264157028877).
Click on the receiver while simulation is running to specify individual IR codes.
### ReceiverTimingAnalysis
This example analyzes the signal delivered by your IR receiver module.
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.
It also computes the MARK_EXCESS_MICROS value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656).
Click on the receiver while simulation is running to specify individual IR codes.
# Tips and tricks
- To port the library to another device, you merely have to extend *IRTimer.hpp*.
- The minimal CPU clock required for receiving is 8MHz.
- To save power, you can use the interrupt mode or polling mode with no-sending detection and power down sleep.
This is **not available** for ATtiny85 running with the High Speed PLL clock (as on Digispark boards)
because of the high startup time from sleep of 4 to 5 ms for this clock. You have to use the ISP to [rewrite the CKSEL fuses](https://github.com/ArminJo/micronucleus-firmware/blob/master/utils/Write%2085%20Fuses%20E2%20DF%20FF%20-%20ISP%20Mode%20%3D%208MHz%20without%20BOD%20and%20Pin5.cmd) and to load the program.
- The best way to **increase the IR power** is to use 2 or 3 IR diodes in series.
One diode requires 1.1 to 1.5 volt so you can supply 3 diodes with a 5 volt output.To keep the current,
you must reduce the resistor by (5 - 1.3) / (5 - 2.6) = 1.5 e.g. from 150 Ω to 100 Ω for 25 mA and 2 diodes with 1.3 volt and a 5 volt supply.
For 3 diodes it requires factor 2.5 e.g. from 150 Ω to 60 Ω.
- A lot of recent IR diodes can be powered with max. 200 mA at 50% duty cycle, but for this you will require an external driver / transistor / (mos)fet.
- In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.
- Sending `IRMP_NEC_PROTOCOL` requires a full 16 bit address. Thus for sending plain NEC with 8 bit address, the 16 bit address must be computed with
`address |= ~((address & 0xFF) << 8);`
# Compile options / macros for this library
To customize the library to different requirements, there are some compile options / macros available, which must be set **before** including the library e.g. with `#include `.
Modify it by setting the value to 1 or 0. Or define the macro with the -D compiler option for global compile (the latter is not possible with the Arduino IDE, so consider using [Sloeber](https://eclipse.baeyens.it).
| Name | Default value | Description |
|-|-:|-|
| `IRMP_INPUT_PIN` | 2 | The pin number which gets compiled in, if not using `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. See also [PinDefinitionsAndMore.h](https://github.com/IRMP-org/IRMP/master/examples/OneProtocol/PinDefinitionsAndMore.h#L32) |
| `IRMP_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for the feedback led which gets compiled in, if not using `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. |
| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my like my BluePill and my ESP8266 board), where the feedback LED is active low. |
| `NO_LED_FEEDBACK_CODE` | disabled | Enable it to disable the feedback LED function. Saves 30 bytes program memory. |
| `IRMP_IRSND_ALLOW_DYNAMIC_PINS` | disabled | Allows to specify pin number at irmp_init() - see above. This requires additional program memory. |
| `IRMP_PROTOCOL_NAMES` | 0 / disabled | Enable protocol number mapping to protocol strings - needs some program memory. |
| `IRMP_USE_COMPLETE_CALLBACK` | 0 / disabled | Use Callback if complete data was received. Requires call to irmp_register_complete_callback_function(). |
| `IRMP_ENABLE_PIN_CHANGE_INTERRUPT` | disabled | Use [Arduino attachInterrupt()](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/) and do **no polling with timer ISR**. This **restricts the available input pins and protocols**. The results are equivalent to results acquired with a sampling rate of 15625 Hz (chosen to avoid time consuming divisions). For AVR boards an own interrupt handler for INT0 or INT1 is used instead of Arduino attachInterrupt(). |
| `IRMP_ENABLE_RELEASE_DETECTION` | 0 / disabled | If user releases a key on the remote control, last protocol/address/command will be returned with flag `IRMP_FLAG_RELEASE` set. |
| `IRMP_HIGH_ACTIVE` | 0 / disabled | Set to 1 if you use a RF receiver, which has an active HIGH output signal. |
| `IRMP_32_BIT` | 0 / disabled | This enables MERLIN protocol, but decreases performance for AVR. Enabled by default for 32 bit platforms. |
| `F_INTERRUPTS` | 15000 | The IRMP sampling frequency.|
| `USE_ONE_TIMER_FOR_IRMP_AND_IRSND` | disabled | **Must** be defined if you use receiving and sending simultaneously, since both use the same timer resource. **Must not** be enabled if you only use receiving. |
| `IRSND_USE_CALLBACK` | 0 / disabled | Calls a function if send output signal changes to active (sending the IR signal). |
| `IR_OUTPUT_IS_ACTIVE_LOW` | disabled | Output LOW for active IR signal. Use it if IR LED is connected between VCC and output pin. |
| `IRSND_GENERATE_NO_SEND_RF` | disabled | Do not generate the carrier frequency (of 38 kHz), just simulate an active low receiver signal. |
| `IRSND_IR_FREQUENCY` | 38000 | The modulation frequency for sent signal. The send signal is generated by bit banging, so the internal interrupt frequency is `IRSND_IR_FREQUENCY * 2`. The send control function is called at a rate of `IRSND_IR_FREQUENCY / 2`, resulting in a send packet signal resolution of 2 on/off periods. |
|-|-|-|
| `IRMP_MEASURE_TIMING` + `IR_TIMING_TEST_PIN` | enabled | For development only. The test pin is switched high at the very beginning and low at the end of the ISR. |
These next macros for **TinyIRReceiver** must be defined in your program before the line `#include ` to take effect.
| Name | Default value | Description |
|-|-:|-|
| `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. |
| `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. |
| `NO_LED_FEEDBACK_CODE` | disabled | Enable it to disable the feedback LED function. Saves 14 bytes program memory. |
### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.
If you have not yet saved the example as your own sketch, then you are instantly in the right library folder.
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.
In both cases the library source and include files are located in the libraries `src` directory.
The modification must be renewed for each new library version!
### Modifying compile options with Sloeber IDE
If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easily define global symbols with *Properties > Arduino > CompileOptions*.

# [Timer usage](https://github.com/IRMP-org/IRMP/blob/master/src/IRTimer.hpp#L39)
The IRMP **receive** library works by polling the input pin at a rate of 10 to 20 kHz. Default is 15 kHz.
Some protocols (NEC, Kaseiko, Denon, RC6, Samsung + Samsg32) can be received **without timer usage**, just by using interrupts from the input pin by defining `IRMP_ENABLE_PIN_CHANGE_INTERRUPT`. There are many protocols which **in principle cannot be decoded** in this mode. See [Interrupt example](examples/Interrupt/Interrupt.ino).
**In interrupt mode, the `micros()` function is used as timebase.**
The IRMP **send** library works by bit banging the output pin at a frequency of 38 kHz. This **avoids blocking waits** and allows to choose an **arbitrary pin**, you are not restricted to PWM generating pins like pin 3 or 11. The interrupts for send pin bit banging require 50% CPU time on a 16 MHz AVR.
If both receiving and sending is required, the timer is set up for receiving and reconfigured for the duration of sending data, thus preventing receiving in polling mode while sending data.
The **tone library (using timer 2) is still available**. You can use it alternating with IR receive and send, see [ReceiveAndSend example](examples/ReceiveAndSend/ReceiveAndSend.ino).
- For AVR **timer 2 (Tone timer)** is used for receiving **and** sending.
For variants, which have no timer 2 like ATtiny85 or ATtiny167, **timer 1** (or timer 0 for digispark core) is used.
- For SAMD **TC3** is used.
- For Apollo3 **Timer 3 segment B** is used.
- For ESP8266 and ESP32 **timer1** is used.
- For STM32 (BluePill) **timer 3 (Servo timer) channel 1** is used as default.
# [AllProtocols](examples/AllProtocols/AllProtocols.ino) example
| Serial LCD output | Arduino Serial Monitor output |
|-|-|
|  |  |
## Sample Protocols
| | | | |
|-|-|-|-|
|  |  | | |
|  | | | |
|  | | | |
|  | | | |
# Documentation at mikrocontroller.net
### English
http://www.mikrocontroller.net/articles/IRMP_-_english
http://www.mikrocontroller.net/articles/IRSND_-_english
### German
http://www.mikrocontroller.net/articles/IRMP
http://www.mikrocontroller.net/articles/IRSND
### German Forum
https://www.mikrocontroller.net/topic/irmp-infrared-multi-protocol-decoder?goto=6996113#6996137
# Revision History
### Version 3.7.0 - Major content contribution by Jörg Riechardt
- Support RC6A20 and RC6A28.
- Sending S100 is not supported.
- Enable repetition for IR60.
- Fix for sending on STM32 with standard peripheral library.
- Includes and initialization for RP2040
- Allow Lego with 19 kHz.
### Version 3.6.4
- Support for ESP32 core 3.x.
- Improved code for MegaTinyCore.
### Version 3.6.3
- Fixed ESP32 send timer bug.
### Version 3.6.2
- Fixed FEEDBACK_LED_IS_ACTIVE_LOW bug.
- Added Kaseikyo Panasonic decode.
- Added ATtiny88 / AVR timer1 timer support.
- Fixed unexpected leading space for irsnd_send_data(...,false).
### Version 3.6.1
- Fixed NO_LED_FEEDBACK_CODE bug.
### Version 3.6.0
- Improved timings by J�rg R.
- Support for NEC 8 bit address.
- Fixed ATmega4809 bug.
- RP2040 support added.
### Version 3.5.1
- Fixed ESP8266 `F_CPU` error introduced with 3.4.1.
### Version 3.5.0
- Renamed *.c.h and *.cpp.h to .hpp. **You must change: #include to: #include !**
- Fix Timer1 initialization for ATtinyX7 parts for ATTinyCore.
- Modifying *digitalWriteFast.h* to be compatible with ATTinyCore Digispark Pro default pin mapping.
- Renamed `initPCIInterrupt()` to `enablePCIInterrupt()` and added `disablePCIInterrupt()`.
- Changed return value for `irsnd_send_data()` to be false on error conditions.
- Fixed `ICACHE_RAM_ATTR` error introduced with 3.4.1.
### Version 3.4.1
- Changed default pins for ATmega328 platform from 3,4,5 to 2,3,4.
- Adapted to TinyCore 0.0.7.
- Renamed macro IRMP_TIMING_TEST_PIN to IR_TIMING_TEST_PIN.
- Changed pins in PinDefinitionsAndMore.h.
- Never send a trailing space for Arduino.
- ATTiny88 support.
### Version 3.4.0
- Added ATtiny3217 / TinyCore support.
- Added Melinera protocol and single repeat for NEC from upstream.
### Version 3.3.5
- Added TinyIRReceiver and updated IRDispatcherDemo examples.
- Fixed "enabling OUTPUT for dynamic pin" bug.
- Improved Apollo3 and MegaCore support.
### Version 3.3.4
- Removed convenience function `irmp_tone()`, since it statically allocates the tone interrupt vector 7.
### Version 3.3.3
- Added ATmega8 support.
- Added `IRSND_GENERATE_NO_SEND_RF` compile switch.
- Added function `irsnd_data_print()`.
- New SendAllProtocols example.
- New DispatcherDemo example.
- Added `IRMP_FEEDBACK_LED_PIN` compile switch.
- Removed `IRMP16` protocol from the all list.
- Added missing Leonardo support.
### Version 3.3.2
- Added missing Medion entry in `irmp_protocol_names`.
- Added function `irmp_print_protocol_name()`.
- Added Teensyduino support.
- Fixed macro redefinitions in IRSND.
### Version 3.3.1
- Fix for function `bool irmp_IsBusy()` if `IRMP_ENABLE_PIN_CHANGE_INTERRUPT` is defined.
### Version 3.3.0
- Added function `bool irmp_IsBusy()`.
### Version 3.2.3
- Fixed warning for missing `USE_ONE_TIMER_FOR_IRMP_AND_IRSND` macro.
### Version 3.2.2
- Removed blocking wait for ATmega32U4 Serial in examples.
- Restored missing line `reset interrupt flags` found by user yumkam.
- Fixed bug for sending only on no AVR platforms.
### Version 3.2.1
- Fixed bug in feedback LED handling for dynamic pins for send and receive.
- Fixed wrong timer selection for STM32F1xx / ARDUINO_ARCH_STM32.
### Version 3.2.0
- MBED support for Arduino Nano 33 BLE.
- Added ARDUINO_ARCH_STM32 definition.
- Fixed ESP8266 wrong memcpy_p definition introduced in 3.0.0.
### Version 3.1.2
- Fixed interrupt mode bug introduced by merging upstream code for version 3.1.0.
- Fixed ESP8266 wrong memcpy_p definition introduced in 3.0.0. - Fix was not complete :-(. Use 3.2.0.
### Version 3.1.1
- Added `MinimalReceiver` example.
### Version 3.1.0
- Added RF_MEDION protocol
- IRAM attribute etc.
- Fixed bug irmp_init used instead of irsnd_init
- New function irmp_print_active_protocols().
- Use timer3 for ESP32.
- Fix missing check for LED pin == 0.
- Merged upstream v3.2.2 + IRMP_ENABLE_RELEASE_DETECTION.
- Dynamic pin for feedback LED added.
### Version 3.0.0
- Support of RF (433MHz) remotes. 2 protocols **Generic 24 bit format** and **X10 format** added.
- MegaAVR (ATmega4809) support.
- Added `IRMP_IRSND_ALLOW_DYNAMIC_PINS` and extended `irmp_init()` and `irsnd_init()`to allow input, output and LED feedback pin selection at runtime.
- Support more protocols simultaneously on 32 bit CPUs.
- Use same pin and enable flag for receive and send feedback LED.
- New function `irmp_print_active_protocols()`.
### Version 2.2.1
- Improved pin layout.
- Fixed bug with stm32duino 1.9.
- Version number.
- Blink13 -> LEDFeedback.
### Version 2.2.0
- Supported **Apollo3** platform.
- Fixed DigisparkPro bug.
### Version 2.1.0
- Supported **SAMD** platform.
- IRSND enabled for non AVR platforms.
### Version 2.0.0
- Added IR send functionality (IRSND).
- Use `TIMER2_COMPB_vect` to be compatible with tone library.
- No longer required to call initPCIInterrupt() manually if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is set.
- Separated code for timer to IRTimer.hpp.
- Separated code for Pin change interrupt to irmpPinChangeInterrupt.hpp.
- Fixed wrong pin numbers for BluePill.
### Version 1.2.2
- Fixed bugs introduced in 1.2.1.
### Version 1.2.1
- Bug for AVR architecture fixed.
- ATtiny85 + ATtiny167 support for ATTinyCore and Digistump core.
- Support for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager.
### Version 1.2.0 - This version contains a bug for the AVR architecture
- Added STM32 M3 (BluePill) support.
### Version 1.1.0
- Added functions `irmp_disable_timer_interrupt()` and `irmp_enable_timer_interrupt()`.
- Added function `irmp_result_print(Print *aSerial)`.
- Improved examples.
### Version 1.0.1
- Added ESP8266 + ESP32 support.
# CI
The library examples are tested with GitHub Actions for the following boards:
- arduino:avr:uno
- arduino:avr:leonardo
- arduino:avr:mega
- arduino:megaavr:nona4809:mode=off
- arduino:samd:arduino_zero_native
- arduino:mbed:nano33ble
- arduino:mbed_rp2040:pico
- rp2040:rp2040:arduino_nano_connect
- digistump:avr:digispark-tiny:clock=clock16
- ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=8pll
- ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
- ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz
- TinyCore:avr:tiny32
- esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
- esp32:esp32:featheresp32:FlashFreq=80
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
- STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
- stm32duino:STM32F1:genericSTM32F103C
- SparkFun:apollo3:sfe_artemis_nano
================================================
FILE: examples/AllProtocols/ADCUtils.h
================================================
/*
* ADCUtils.h
*
* Copyright (C) 2016-2022 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* ArduinoUtils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef _ADC_UTILS_H
#define _ADC_UTILS_H
#include
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
#define ADC_UTILS_ARE_AVAILABLE
// External Reference Current is 150 uA for 5 V and 100 uA for 3.5 V
#define READING_FOR_AREF 1024 // Datasheet 24.2: The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB
#define MAX_ADC_VALUE 1023
// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz
#define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE4 2 // 52 microseconds per ADC conversion at 1 MHz
// PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 MHz Clock => 9,6 kHz
#define ADC_PRESCALE8 3 // 104 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE16 4 // 13/208 microseconds per ADC conversion at 16/1 MHz - degradations in linearity at 16 MHz
#define ADC_PRESCALE32 5 // 26/416 microseconds per ADC conversion at 16/1 MHz - very good linearity at 16 MHz
#define ADC_PRESCALE64 6 // 52 microseconds per ADC conversion at 16 MHz
#define ADC_PRESCALE128 7 // 104 microseconds per ADC conversion at 16 MHz --- Arduino default
// definitions for 0.1 ms conversion time
#if (F_CPU == 1000000)
#define ADC_PRESCALE ADC_PRESCALE8
#elif (F_CPU == 8000000)
#define ADC_PRESCALE ADC_PRESCALE64
#elif (F_CPU == 16000000)
#define ADC_PRESCALE ADC_PRESCALE128
#endif
/*
* Reference shift values are complicated for ATtinyX5 since we have the extra register bit REFS2
* in ATTinyCore, this bit is handled programmatical and therefore the defines are different.
* To keep my library small, I use the changed defines.
* After including this file you can not call the ATTinyCore readAnalog functions reliable, if you specify references other than default!
*/
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// defines are for ADCUtils.cpp, they can be used WITHOUT bit reordering
#undef DEFAULT
#undef EXTERNAL
#undef INTERNAL1V1
#undef INTERNAL
#undef INTERNAL2V56
#undef INTERNAL2V56_EXTCAP
#define DEFAULT 0
#define EXTERNAL 4
#define INTERNAL1V1 8
#define INTERNAL INTERNAL1V1
#define INTERNAL2V56 9
#define INTERNAL2V56_EXTCAP 13
#define SHIFT_VALUE_FOR_REFERENCE REFS2
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1) | _BV(REFS2))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#else // AVR_ATtiny85
#define SHIFT_VALUE_FOR_REFERENCE REFS0
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#endif
// Temperature channel definitions - 1 LSB / 1 degree Celsius
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define ADC_TEMPERATURE_CHANNEL_MUX 15
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define ADC_ISCR_CHANNEL_MUX 3
#define ADC_TEMPERATURE_CHANNEL_MUX 11
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 14
#define ADC_VCC_4TH_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x1F
#elif defined(__AVR_ATmega328P__)
#define ADC_TEMPERATURE_CHANNEL_MUX 8
#define ADC_1_1_VOLT_CHANNEL_MUX 14
#define ADC_GND_CHANNEL_MUX 15
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATmega644P__)
#define ADC_TEMPERATURE_CHANNEL_MUX // not existent
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATmega32U4__)
#define ADC_TEMPERATURE_CHANNEL_MUX 0x27
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x3F
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x1F
#define INTERNAL INTERNAL1V1
#else
#error "No temperature channel definitions specified for this AVR CPU"
#endif
/*
* Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion)
*
* Default values are suitable for Li-ion batteries.
* We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
* But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
*/
#if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
#endif
#if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
#endif
#if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5250 // + 5 % operation voltage
#endif
#if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5500 // +10 %. Max recommended operation voltage
#endif
#if !defined(VCC_CHECK_PERIOD_MILLIS)
#define VCC_CHECK_PERIOD_MILLIS 10000L // 10 seconds period of VCC checks
#endif
#if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP)
#define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4300 // Assume USB powered above this voltage
#endif
#if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT 4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN.
// In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply
#endif
extern long sLastVCCCheckMillis;
extern uint8_t sVCCTooLowCounter;
uint16_t readADCChannel();
uint16_t readADCChannel(uint8_t aADCChannelNumber);
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber);
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent);
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples);
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
uint8_t aAllowedDifference, uint8_t aMaxRetries);
void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber);
void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber);
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference);
/*
* readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage
*/
float getVCCVoltageSimple(void);
void readVCCVoltageSimple(void);
void readVCCVoltageMillivoltSimple(void);
void readVCCVoltage(void);
uint16_t getVCCVoltageMillivolt(void);
void readVCCVoltageMillivolt(void);
uint16_t getVCCVoltageReadingFor1_1VoltReference(void);
uint16_t printVCCVoltageMillivolt(Print *aSerial);
void readAndPrintVCCVoltageMillivolt(Print *aSerial);
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement);
float getCPUTemperatureSimple(void);
float getCPUTemperature(void);
float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated
bool isVCCUSBPowered();
bool isVCCUSBPowered(Print *aSerial);
bool isVCCUndervoltageMultipleTimes();
void resetCounterForVCCUndervoltageMultipleTimes();
bool isVCCUndervoltage();
bool isVCCEmergencyUndervoltage();
bool isVCCOvervoltage();
bool isVCCOvervoltageSimple(); // Version using readVCCVoltageMillivoltSimple()
bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimple()
#endif // defined(__AVR__) ...
/*
* The next variables and functions are defined as stubs on non-AVR platforms to allow for seamless compiling
*/
extern float sVCCVoltage;
extern uint16_t sVCCVoltageMillivolt;
uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint16_t getVCCVoltageMillivoltSimple(void);
float getVCCVoltage(void);
float getCPUTemperature(void);
#endif // _ADC_UTILS_H
================================================
FILE: examples/AllProtocols/ADCUtils.hpp
================================================
/*
* ADCUtils.hpp
*
* ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h.
*
* Copyright (C) 2016-2023 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* ArduinoUtils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef _ADC_UTILS_HPP
#define _ADC_UTILS_HPP
#include "ADCUtils.h"
#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected
#define ADC_UTILS_ARE_INCLUDED
// Helper macro for getting a macro definition as string
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
#if !defined(BITS_PER_BYTE)
#define BITS_PER_BYTE 8
#endif
/*
* By replacing this value with the voltage you measured a the AREF pin after a conversion
* with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV.
*/
#if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT)
#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100 // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
#endif
// Union to speed up the combination of low and high bytes to a word
// it is not optimal since the compiler still generates 2 unnecessary moves
// but using -- value = (high << 8) | low -- gives 5 unnecessary instructions
union WordUnionForADCUtils {
struct {
uint8_t LowByte;
uint8_t HighByte;
} UByte;
uint16_t UWord;
int16_t Word;
uint8_t *BytePointer;
};
/*
* Enable this to see information on each call.
* Since there should be no library which uses Serial, it should only be enabled for development purposes.
*/
#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
#if defined(INFO)
#define LOCAL_INFO
#else
//#define LOCAL_INFO // This enables debug output only for this file
#endif
/*
* Persistent storage for VCC value
*/
float sVCCVoltage;
uint16_t sVCCVoltageMillivolt;
// for isVCCTooLowMultipleTimes()
long sLastVCCCheckMillis;
uint8_t sVCCTooLowCounter = 0;
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
* Use previous settings
*/
uint16_t readADCChannel() {
WordUnionForADCUtils tUValue;
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);
// wait for single conversion to finish
loop_until_bit_is_clear(ADCSRA, ADSC);
// Get value
tUValue.UByte.LowByte = ADCL;
tUValue.UByte.HighByte = ADCH;
return tUValue.UWord;
// return ADCL | (ADCH <<8); // needs 4 bytes more
}
/*
* Use new channel aADCChannelNumber, but do not wait for channel switching
*/
uint16_t readADCChannel(uint8_t aADCChannelNumber) {
WordUnionForADCUtils tUValue;
ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);
// wait for single conversion to finish
loop_until_bit_is_clear(ADCSRA, ADSC);
// Get value
tUValue.UByte.LowByte = ADCL;
tUValue.UByte.HighByte = ADCH;
return tUValue.UWord;
// return ADCL | (ADCH <<8); // needs 4 bytes more
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
*/
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
WordUnionForADCUtils tUValue;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);
// wait for single conversion to finish
loop_until_bit_is_clear(ADCSRA, ADSC);
// Get value
tUValue.UByte.LowByte = ADCL;
tUValue.UByte.HighByte = ADCH;
return tUValue.UWord;
}
uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber) {
WordUnionForADCUtils tUValue;
ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);
// wait for single conversion to finish
loop_until_bit_is_clear(ADCSRA, ADSC);
// Get value
tUValue.UByte.LowByte = ADCL;
tUValue.UByte.HighByte = ADCH;
return tUValue.UWord;
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
* Does NOT restore ADMUX after reading
*/
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
return readADCChannelWithReference(aADCChannelNumber, aReference);
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
* Restores ADMUX after reading
*/
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference) {
uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
uint16_t tResult = readADCChannelWithReference(aADCChannelNumber, aReference);
checkAndWaitForReferenceAndChannelToSwitch(tOldADMUX & MASK_FOR_ADC_CHANNELS, tOldADMUX >> SHIFT_VALUE_FOR_REFERENCE);
return tResult;
}
/*
* To prepare reference and ADMUX for next measurement
*/
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference) {
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
}
/*
* 100 kOhm requires < 100 us, 1 MOhm requires 120 us S&H switching time
*/
void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber) {
ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE);
delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
}
void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber) {
ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
}
/*
* @return original ADMUX register content for optional later restoring values
* All experimental values are acquired by using the ADCSwitchingTest example from this library
*/
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference) {
uint8_t tOldADMUX = ADMUX;
/*
* Must wait >= 7 us if reference has to be switched from 1.1 volt/INTERNAL to VCC/DEFAULT (seen on oscilloscope)
* This is done after the 2 ADC clock cycles required for Sample & Hold :-)
*
* Must wait >= 7600 us for Nano board >= 6200 for Uno board if reference has to be switched from VCC/DEFAULT to 1.1 volt/INTERNAL
* Must wait >= 200 us if channel has to be switched to 1.1 volt internal channel if S&H was at 5 Volt
*/
uint8_t tNewReference = (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | tNewReference;
#if defined(INTERNAL2V56)
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) {
#else
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) {
#endif
#if defined(LOCAL_DEBUG)
Serial.println(F("Switch from DEFAULT to INTERNAL"));
#endif
/*
* Switch reference from DEFAULT to INTERNAL
*/
delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board
} else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK) != aADCChannelNumber) {
if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
/*
* Internal 1.1 Volt channel requires <= 200 us for Nano board
*/
delayMicroseconds(350); // 350 was ok and 300 was too less for UltimateBatteryTester - result was 226 instead of 225
} else {
/*
* 100 kOhm requires < 100 us, 1 MOhm requires 120 us S&H switching time
*/
delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
}
}
return tOldADMUX;
}
/*
* Oversample and multiple samples only makes sense if you expect a noisy input signal
* It does NOT increase the precision of the measurement, since the ADC has insignificant noise
*/
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent) {
return readADCChannelWithReferenceOversample(aADCChannelNumber, DEFAULT, aOversampleExponent);
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
*/
uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE);
uint8_t tCount = _BV(aOversampleExponent);
for (uint8_t i = 0; i < tCount; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
// return rounded value
return ((tSumValue + (tCount >> 1)) >> aOversampleExponent);
}
/*
* Use ADC_PRESCALE32 which gives 26 us conversion time and good linearity for 16 MHz Arduino
*/
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE32);
uint8_t tCount = _BV(aOversampleExponent);
for (uint8_t i = 0; i < tCount; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return ((tSumValue + (tCount >> 1)) >> aOversampleExponent);
}
/*
* Returns sum of all sample values
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h.
* @ param aNumberOfSamples If > 64 an overflow may occur.
*/
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE);
for (uint8_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tSumValue;
}
/*
* Returns sum of all sample values
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino for ADC_PRESCALE128 in ADCUtils.h.
* @ param aPrescale can be one of ADC_PRESCALE2, ADC_PRESCALE4, 8, 16, 32, 64, 128.
* ADC_PRESCALE32 is recommended for excellent linearity and fast readout of 26 microseconds
* @ param aNumberOfSamples If > 16k an overflow may occur.
*/
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
uint16_t aNumberOfSamples) {
uint32_t tSumValue = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);
for (uint16_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tSumValue;
}
/*
* Returns sum of all sample values
* Assumes, that channel and reference are still set to the right values
* @ param aNumberOfSamples If > 16k an overflow may occur.
*/
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples) {
uint32_t tSumValue = 0;
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);
for (uint16_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// Add value
tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
// tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tSumValue;
}
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
* @return the maximum value of aNumberOfSamples samples.
*/
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) {
uint16_t tADCValue = 0;
uint16_t tMaximum = 0;
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE32);
for (uint16_t i = 0; i < aNumberOfSamples; i++) {
/*
* wait for free running conversion to finish.
* Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
*/
loop_until_bit_is_set(ADCSRA, ADIF);
ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
// check value
tADCValue = ADCL | (ADCH << 8);
if (tADCValue > tMaximum) {
tMaximum = tADCValue;
}
}
ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
return tMaximum;
}
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
* @return the maximum value during aMicrosecondsToAquire measurement.
*/
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
uint16_t tNumberOfSamples = aMicrosecondsToAquire / 26;
return readADCChannelWithReferenceMax(aADCChannelNumber, aReference, tNumberOfSamples);
}
/*
* aMaxRetries = 255 -> try forever
* @return (tMax + tMin) / 2
*/
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
uint8_t aAllowedDifference, uint8_t aMaxRetries) {
int tValues[4]; // last value is in tValues[3]
int tMin;
int tMax;
/*
* Initialize first 4 values before checking
*/
tValues[0] = readADCChannelWithReference(aADCChannelNumber, aReference);
for (int i = 1; i < 4; ++i) {
if (aDelay != 0) {
delay(aDelay); // Minimum is only 3 delays!
}
tValues[i] = readADCChannelWithReference(aADCChannelNumber, aReference);
}
do {
/*
* Get min and max of the last 4 values
*/
tMin = READING_FOR_AREF;
tMax = 0;
for (uint_fast8_t i = 0; i < 4; ++i) {
if (tValues[i] < tMin) {
tMin = tValues[i];
}
if (tValues[i] > tMax) {
tMax = tValues[i];
}
}
/*
* check for terminating condition
*/
if ((tMax - tMin) <= aAllowedDifference) {
break;
} else {
/*
* Get next value
*/
// Serial.print("Difference=");
// Serial.println(tMax - tMin);
// Move values to front
for (int i = 0; i < 3; ++i) {
tValues[i] = tValues[i + 1];
}
// and wait before getting next value
if (aDelay != 0) {
delay(aDelay);
}
tValues[3] = readADCChannelWithReference(aADCChannelNumber, aReference);
}
if (aMaxRetries != 255) {
aMaxRetries--;
}
} while (aMaxRetries > 0);
#if defined(LOCAL_DEBUG)
if(aMaxRetries == 0) {
Serial.print(F("No 4 equal values for difference "));
Serial.print(aAllowedDifference);
Serial.print(F(" found "));
Serial.print(tValues[0]);
Serial.print(' ');
Serial.print(tValues[1]);
Serial.print(' ');
Serial.print(tValues[2]);
Serial.print(' ');
Serial.println(tValues[3]);
} else {
Serial.print(aMaxRetries);
Serial.println(F(" retries left"));
}
#endif
return (tMax + tMin) / 2;
}
/*
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
* !!! Resolution is only 20 millivolt !!!
* Raw reading of 1.1 V is 225 at 5 V.
* Raw reading of 1.1 V is 221 at 5.1 V.
* Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
* Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
*/
float getVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return ((READING_FOR_AREF * 1.1 * 4) / tVCC);
}
/*
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
* !!! Resolution is only 20 millivolt !!!
*/
uint16_t getVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
}
/*
* Gets the hypothetical 14 bit reading of VCC using 1.1 volt reference
* Similar to getVCCVoltageMillivolt() * 1024 / 1100
*/
uint16_t getVCCVoltageReadingFor1_1VoltReference(void) {
uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
return (((uint32_t)READING_FOR_AREF * READING_FOR_AREF) / tVCC);
}
/*
* !!! Resolution is only 20 millivolt !!!
*/
float getVCCVoltage(void) {
return (getVCCVoltageMillivolt() / 1000.0);
}
/*
* Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference.
* Handles reference and channel switching by introducing the appropriate delays.
* !!! Resolution is only 20 millivolt !!!
* Raw reading of 1.1 V is 225 at 5 V.
* Raw reading of 1.1 V is 221 at 5.1 V.
* Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
* Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
*/
uint16_t getVCCVoltageMillivolt(void) {
uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
}
/*
* Does not set sVCCVoltageMillivolt
*/
uint16_t printVCCVoltageMillivolt(Print *aSerial) {
aSerial->print(F("VCC="));
uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt();
aSerial->print(tVCCVoltageMillivolt);
aSerial->println(" mV");
return tVCCVoltageMillivolt;
}
void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
aSerial->print(F("VCC="));
sVCCVoltageMillivolt = getVCCVoltageMillivolt();
aSerial->print(sVCCVoltageMillivolt);
aSerial->println(" mV");
}
/*
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
* !!! Resolution is only 20 millivolt !!!
*/
void readVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltage = (READING_FOR_AREF * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}
/*
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
* !!! Resolution is only 20 millivolt !!!
*/
void readVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}
/*
* !!! Resolution is only 20 millivolt !!!
*/
void readVCCVoltage(void) {
sVCCVoltage = getVCCVoltageMillivolt() / 1000.0;
}
/*
* Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference.
* Handles reference and channel switching by introducing the appropriate delays.
* !!! Resolution is only 20 millivolt !!!
* Sets also the sVCCVoltageMillivolt variable.
*/
void readVCCVoltageMillivolt(void) {
uint16_t tVCCVoltageMillivoltRaw = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
}
/*
* Get voltage at ADC channel aADCChannelForVoltageMeasurement
* aVCCVoltageMillivolt is assumed as reference voltage
*/
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
* Get voltage at ADC channel aADCChannelForVoltageMeasurement
* Reference voltage VCC is determined just before
*/
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, INTERNAL);
return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
* This does not really work for the UNO board, because it has no series Diode in the USB VCC
* and therefore a very low voltage drop.
*/
bool isVCCUSBPowered() {
readVCCVoltageMillivolt();
return (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT < sVCCVoltageMillivolt
&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT);
}
/*
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
*/
bool isVCCUSBPowered(Print *aSerial) {
readVCCVoltageMillivolt();
aSerial->print(F("USB powered is "));
bool tReturnValue;
if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT
< sVCCVoltageMillivolt&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
tReturnValue = true;
aSerial->print(F("true "));
} else {
tReturnValue = false;
aSerial->print(F("false "));
}
printVCCVoltageMillivolt(aSerial);
return tReturnValue;
}
/*
* It checks every 10 seconds for 6 times, and then returns once true if the undervoltage condition ( <3.4V ) still applies.
* @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown
*/
bool isVCCUndervoltageMultipleTimes() {
/*
* Check VCC every VCC_CHECK_PERIOD_MILLIS - default is 10 seconds
*/
if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
sLastVCCCheckMillis = millis();
# if defined(INFO)
readAndPrintVCCVoltageMillivolt(&Serial);
# else
readVCCVoltageMillivolt();
# endif
/*
* Do not check again if shutdown signaling (sVCCTooLowCounter >= 6) has happened
*/
if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) { // VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP = 6
if (sVCCVoltageMillivolt > VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
sVCCTooLowCounter = 0; // reset counter
} else {
/*
* Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then signal shut down.
*/
if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
// emergency shutdown
sVCCTooLowCounter = VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP;
# if defined(LOCAL_INFO)
Serial.println(
F(
"Undervoltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown"));
# endif
} else {
sVCCTooLowCounter++;
# if defined(LOCAL_INFO)
Serial.print(sVCCVoltageMillivolt);
Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV -> undervoltage detected: "));
Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter);
Serial.println(F(" attempts left"));
# endif
}
if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
/*
* 6 times voltage too low -> return signal for shutdown etc.
*/
return true;
}
}
}
}
return false;
}
/*
* Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached
*/
bool isVCCUndervoltage() {
readVCCVoltageMillivolt();
return (sVCCVoltageMillivolt < VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT);
}
/*
* Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached
*/
bool isVCCEmergencyUndervoltage() {
readVCCVoltageMillivolt();
return (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT);
}
void resetCounterForVCCUndervoltageMultipleTimes() {
sVCCTooLowCounter = 0;
}
/*
* Recommended VCC is 1.8 V to 5.5 V, absolute maximum VCC is 6.0 V.
* Check for 5.25 V, because such overvoltage is quite unlikely to happen during regular operation.
* Raw reading of 1.1 V is 225 at 5 V.
* Raw reading of 1.1 V is 221 at 5.1 V.
* Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
* Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
* Raw reading of 1.1 V is 1126000 / VCC_MILLIVOLT
* @return true if 5 % overvoltage reached
*/
bool isVCCOvervoltage() {
readVCCVoltageMillivolt();
return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}
bool isVCCOvervoltageSimple() {
readVCCVoltageMillivoltSimple();
return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}
// Version not using readVCCVoltageMillivoltSimple()
bool isVCCTooHighSimple() {
ADMUX = ADC_1_1_VOLT_CHANNEL_MUX | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE128); // 128 -> 104 microseconds per ADC conversion at 16 MHz --- Arduino default
// wait for single conversion to finish
loop_until_bit_is_clear(ADCSRA, ADSC);
// Get value
uint16_t tRawValue = ADCL | (ADCH << 8);
return tRawValue < 1126000 / VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT;
}
/*
* Temperature sensor is enabled by selecting the appropriate channel.
* Different formula for 328P and 328PB!
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only use INTERNAL reference (e.g. only call getTemperatureSimple()) in your program.
*/
float getCPUTemperatureSimple(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
return 0.0;
#else
// use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-(
uint16_t tTemperatureRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2);
#if defined(LOCAL_DEBUG)
Serial.print(F("TempRaw="));
Serial.println(tTemperatureRaw);
#endif
#if defined(__AVR_ATmega328PB__)
tTemperatureRaw -= 245;
return (float)tTemperatureRaw;
#elif defined(__AVR_ATtiny85__)
tTemperatureRaw -= 273; // 273 and 1.1666 are values from the datasheet
return (float)tTemperatureRaw / 1.1666;
#else
tTemperatureRaw -= 317;
return (float) tTemperatureRaw / 1.22;
#endif
#endif
}
/*
* Handles usage of 1.1 V reference and channel switching by introducing the appropriate delays.
*/
float getTemperature(void) {
return getCPUTemperature();
}
float getCPUTemperature(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
return 0.0;
#else
// use internal 1.1 volt as reference
checkAndWaitForReferenceAndChannelToSwitch(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL);
return getCPUTemperatureSimple();
#endif
}
#else // defined(ADC_UTILS_ARE_AVAILABLE)
// Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors
/*
* Persistent storage for VCC value
*/
float sVCCVoltage;
uint16_t sVCCVoltageMillivolt;
uint16_t getVCCVoltageMillivoltSimple(void){
return 3300;
}
uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber __attribute__((unused)),
uint8_t aReference __attribute__((unused)), uint8_t aOversampleExponent __attribute__((unused))) {
return 0;
}
float getCPUTemperature() {
return 20.0;
}
float getVCCVoltage() {
return 3.3;
}
#endif // defined(ADC_UTILS_ARE_AVAILABLE)
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#if defined(LOCAL_INFO)
#undef LOCAL_INFO
#endif
#endif // _ADC_UTILS_HPP
================================================
FILE: examples/AllProtocols/AllProtocols.ino
================================================
/*
* AllProtocols.cpp
*
* Accepts 40 protocols concurrently
* If you specify F_INTERRUPTS to 20000 at line 86 (default is 15000) it supports LEGO + RCMM protocols, but disables PENTAX and GREE protocols.
* if you see performance issues, you can disable MERLIN Protocol at line 88.
*
* Uses a callback function which is called every time a complete IR command was received.
* Prints data to LCD connected parallel at pin 4-9 or serial at pin A4, A5
*
* Copyright (C) 2019-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
#include "PinDefinitionsAndMore.h"
/*
* Set input pin and output pin definitions etc.
*/
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - needs some program memory ~ 420 bytes here
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
#if __SIZEOF_INT__ == 4
#define F_INTERRUPTS 20000 // Instead of default 15000 to support LEGO + RCMM protocols
#else
//#define F_INTERRUPTS 20000 // Instead of default 15000 to support LEGO + RCMM protocols, but this in turn disables PENTAX and GREE protocols :-(
//#define IRMP_32_BIT 1 // This enables MERLIN protocol, but decreases performance for AVR.
#endif
#include // This enables all possible protocols
//#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irmp_data;
/*
* Activate the type of LCD you use
* Default is parallel LCD with 2 rows of 16 characters (1602).
* Serial LCD has the disadvantage, that the first repeat is not detected,
* because of the long lasting serial communication.
*/
//#define USE_NO_LCD
//#define USE_SERIAL_LCD
/*
* Define the size of your LCD
*/
//#define USE_2004_LCD
#if defined(USE_2004_LCD)
// definitions for a 2004 LCD
#define LCD_COLUMNS 20
#define LCD_ROWS 4
#else
#define USE_1602_LCD
// definitions for a 1602 LCD
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#endif
#if defined(USE_SERIAL_LCD)
#include "LiquidCrystal_I2C.hpp" // Use an up to date library version, which has the init method
LiquidCrystal_I2C myLCD(0x27, LCD_COLUMNS, LCD_ROWS); // set the LCD address to 0x27 for a 16 chars and 2 line display
#elif !defined(USE_NO_LCD)
#include "LiquidCrystal.h"
#define USE_PARALLEL_LCD
//LiquidCrystal myLCD(4, 5, 6, 7, 8, 9);
LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
#endif
#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
#define USE_LCD
# if defined(ADC_UTILS_ARE_AVAILABLE)
// For cyclically display of VCC
#include "ADCUtils.hpp"
#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
uint32_t volatile sMillisOfLastVoltagePrint;
# endif
void printIRResultOnLCD();
size_t printHex(uint16_t aHexByteValue);
#endif
void handleReceivedIRData();
bool volatile sIRMPDataAvailable = false;
void setup()
{
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) \
|| defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN
irmp_register_complete_callback_function(&handleReceivedIRData);
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
#if defined(USE_SERIAL_LCD)
Serial.println(F("With serial LCD connection, the first repeat is not detected, because of the long lasting serial communication!"));
#endif
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
getVCCVoltageMillivoltSimple(); // to initialize ADC mux and reference
#endif
#if defined(USE_SERIAL_LCD)
myLCD.init();
myLCD.clear();
myLCD.backlight(); // Switch backlight LED on
#endif
#if defined(USE_PARALLEL_LCD)
myLCD.begin(LCD_COLUMNS, LCD_ROWS); // This also clears display
#endif
#if defined(USE_LCD)
myLCD.setCursor(0, 0);
myLCD.print(F("IRMP all v" VERSION_IRMP));
myLCD.setCursor(0, 1);
myLCD.print(F(__DATE__));
#endif
}
void loop()
{
if (sIRMPDataAvailable)
{
sIRMPDataAvailable = false;
/*
* Serial output
* takes 2 milliseconds at 115200
*/
irmp_result_print(&irmp_data);
#if defined(USE_LCD)
# if defined(USE_SERIAL_LCD)
// This suppresses the receive of the 1. NEC repeat
disableIRTimerInterrupt(); // disable timer interrupt, since it disturbs the LCD serial output
# endif
printIRResultOnLCD();
# if defined(USE_SERIAL_LCD)
enableIRTimerInterrupt();
# endif
#endif
}
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
/*
* Periodically print VCC
*/
if (millis() - sMillisOfLastVoltagePrint > MILLIS_BETWEEN_VOLTAGE_PRINT)
{
sMillisOfLastVoltagePrint = millis();
uint16_t tVCC = getVCCVoltageMillivoltSimple();
char tVoltageString[5];
dtostrf(tVCC / 1000.0, 4, 2, tVoltageString);
myLCD.setCursor(11, 0);
myLCD.print(tVoltageString);
myLCD.print('V');
}
#endif
}
/*
* Here we know, that data is available.
* Since this function is executed in Interrupt handler context, make it short and do not use delay() etc.
* In order to enable other interrupts you can call interrupts() (enable interrupt again) after getting data.
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR handleReceivedIRData()
#else
void handleReceivedIRData()
#endif
{
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
// reset voltage display timer
sMillisOfLastVoltagePrint = millis();
#endif
/*
* Just print the data to Serial and LCD
*/
irmp_get_data(&irmp_data);
sIRMPDataAvailable = true;
}
#if defined(USE_LCD)
/*
* LCD output for 1602 and 2004 LCDs
* 40 - 55 Milliseconds per initial output for a 1602 LCD
* for a 2004 LCD the initial clearing adds 55 ms.
* The expander runs at 100 kHz :-(
* 8 milliseconds for 8 bit; 10 ms for 16 bit code output
* 3 milliseconds for repeat output
*
*/
void printIRResultOnLCD()
{
static uint8_t sLastProtocolIndex;
static uint16_t sLastProtocolAddress;
# if (LCD_ROWS >= 4)
static uint8_t sLastCommandPrintPosition = 13;
const uint8_t tStartRow = 2;
# else
static uint16_t sLastCommand;
static uint8_t sLastCommandPrintPosition;
const uint8_t tStartRow = 0;
bool tDisplayWasCleared = false;
# endif
/*
* Print only if protocol or address has changed
*/
if (sLastProtocolIndex != irmp_data.protocol || sLastProtocolAddress != irmp_data.address)
{
sLastProtocolIndex = irmp_data.protocol;
sLastProtocolAddress = irmp_data.address;
# if (LCD_ROWS >= 4)
// clear data lines
myLCD.setCursor(0, tStartRow);
myLCD.print(F(" "));
myLCD.setCursor(0, tStartRow + 1);
myLCD.print(F(" "));
# else
myLCD.clear();
tDisplayWasCleared = true;
# endif
/*
* Show protocol name
*/
myLCD.setCursor(0, tStartRow);
# if defined(__AVR__)
const char *tProtocolStringPtr = (char*) pgm_read_word(&irmp_protocol_names[irmp_data.protocol]);
myLCD.print((__FlashStringHelper*) (tProtocolStringPtr));
# else
myLCD.print(irmp_protocol_names[irmp_data.protocol]);
# endif
/*
* Show address
*/
myLCD.setCursor(0, tStartRow + 1);
myLCD.print(F("A="));
printHex(irmp_data.address);
# if (LCD_COLUMNS > 16)
/*
* Print prefix of command here, since it is constant string
*/
myLCD.setCursor(9, tStartRow + 1);
myLCD.print(F("C="));
# endif
}
else
{
/*
* Show or clear repetition flag
*/
# if (LCD_COLUMNS > 16)
myLCD.setCursor(18, tStartRow + 1);
# else
myLCD.setCursor(15, tStartRow + 1);
# endif
if (irmp_data.flags & IRMP_FLAG_REPETITION)
{
myLCD.print('R');
return; // Since it is a repetition, printed data has not changed
}
else
{
myLCD.print(' ');
}
}
/*
* Command prefix
*/
uint16_t tCommand = irmp_data.command;
# if (LCD_COLUMNS <= 16)
// check if prefix position must change
if (tDisplayWasCleared || (sLastCommand > 0x100 && tCommand < 0x100) || (sLastCommand < 0x100 && tCommand > 0x100))
{
sLastCommand = tCommand;
/*
* Print prefix for 8/16 bit commands
*/
if (tCommand >= 0x100)
{
sLastCommandPrintPosition = 9;
}
else
{
myLCD.setCursor(9, tStartRow + 1);
myLCD.print(F("C="));
sLastCommandPrintPosition = 11;
}
}
# endif
/*
* Command data
*/
myLCD.setCursor(sLastCommandPrintPosition, tStartRow + 1);
printHex(tCommand);
}
size_t printHex(uint16_t aHexByteValue) {
myLCD.print(F("0x"));
size_t tPrintSize = 2;
if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) {
myLCD.print('0'); // leading 0
tPrintSize++;
}
return myLCD.print(aHexByteValue, HEX) + tPrintSize;
}
#endif // defined(USE_LCD)
================================================
FILE: examples/AllProtocols/LiquidCrystal_I2C.h
================================================
//YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h
#include
#include "Print.h"
#if !defined(USE_SOFT_I2C_MASTER) && !defined(USE_SOFT_WIRE)
#include
#endif
// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00
// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00
// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00
// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
#define En 0b00000100 // Enable bit
#define Rw 0b00000010 // Read/Write bit
#define Rs 0b00000001 // Register select bit
class LiquidCrystal_I2C : public Print {
public:
LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
void clear();
void home();
void noDisplay();
void display();
void noBlink();
void blink();
void noCursor();
void cursor();
void scrollDisplayLeft();
void scrollDisplayRight();
void printLeft();
void printRight();
void leftToRight();
void rightToLeft();
void shiftIncrement();
void shiftDecrement();
void noBacklight();
void backlight();
void autoscroll();
void noAutoscroll();
void createChar(uint8_t, uint8_t[]);
void createChar(uint8_t location, const char *charmap);
// Example: const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000};
void setCursor(uint8_t, uint8_t);
size_t write(uint8_t);
void command(uint8_t);
void init();
void oled_init();
////compatibility API function aliases
void blink_on(); // alias for blink()
void blink_off(); // alias for noBlink()
void cursor_on(); // alias for cursor()
void cursor_off(); // alias for noCursor()
void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar()
void printstr(const char[]);
////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end);
private:
void init_priv();
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void expanderWrite(uint8_t);
void pulseEnable(uint8_t);
uint8_t _Addr;
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;
uint8_t _numlines;
bool _oled;
uint8_t _cols;
uint8_t _rows;
uint8_t _backlightval;
};
#endif
================================================
FILE: examples/AllProtocols/LiquidCrystal_I2C.hpp
================================================
// LiquidCrystal_I2C.hpp
// Based on the work by DFRobot
/*
* Extensions made by AJ 2023
* Removed Arduino 0.x support
* Added SoftI2CMaste support, which drastically reduces program size.
* Added OLED stuff
* Added createChar() with PROGMEM input
* Added fast timing
*/
#ifndef _LIQUID_CRYSTAL_I2C_HPP
#define _LIQUID_CRYSTAL_I2C_HPP
#include "Arduino.h"
#if defined(__AVR__) && !defined(USE_SOFT_I2C_MASTER) && __has_include("SoftI2CMasterConfig.h")
#define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.hpp"
#endif
#include "LiquidCrystal_I2C.h"
#include
inline size_t LiquidCrystal_I2C::write(uint8_t value) {
send(value, Rs);
return 1;
}
#if defined(USE_SOFT_I2C_MASTER)
//#define USE_SOFT_I2C_MASTER_H_AS_PLAIN_INCLUDE
#include "SoftI2CMasterConfig.h" // Include configuration for sources
#include "SoftI2CMaster.h" // include sources
#elif defined(USE_SOFT_WIRE)
#define USE_SOFTWIRE_H_AS_PLAIN_INCLUDE
#include "SoftWire.h"
#endif
#if defined(__AVR__)
/*
* The datasheet says: a command need > 37us to settle. Enable pulse must be > 450ns.
* Use no delay for enable pulse after each command,
* because the overhead of this library seems to be using the 37 us and 450 ns.
* At least it works perfectly for all my LCD's connected to Uno, Nano etc.
* and it saves a lot of time in realtime applications using LCD as display,
* like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter
*/
#define USE_FAST_TIMING
#endif
// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
// DL = 1; 8-bit interface data
// N = 0; 1-line display
// F = 0; 5x8 dot character font
// 3. Display on/off control:
// D = 0; Display off
// C = 0; Cursor off
// B = 0; Blinking off
// 4. Entry mode set:
// I/D = 1; Increment by 1
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows) {
_Addr = lcd_Addr;
_cols = lcd_cols;
_rows = lcd_rows;
_backlightval = LCD_NOBACKLIGHT;
_oled = false;
}
void LiquidCrystal_I2C::oled_init() {
_oled = true;
init_priv();
}
void LiquidCrystal_I2C::init() {
init_priv();
}
void LiquidCrystal_I2C::init_priv() {
#if defined(USE_SOFT_I2C_MASTER)
i2c_init();
#else
Wire.begin();
#endif
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
begin(_cols, _rows);
}
void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) {
_displayfunction |= LCD_5x10DOTS;
}
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// according to datasheet, we need at least 40ms after power rises above 2.7V
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
delay(50);
// Now we pull both RS and R/W low to begin commands
expanderWrite(_backlightval); // reset expander and turn backlight off (Bit 8 =1)
delay(1000);
//put the LCD into 4 bit mode
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46
// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// second try
write4bits(0x03 << 4);
delayMicroseconds(4500); // wait min 4.1ms
// third go!
write4bits(0x03 << 4);
delayMicroseconds(150);
// finally, set to 4-bit interface
write4bits(0x02 << 4);
// set # lines, font size, etc.
command(LCD_FUNCTIONSET | _displayfunction);
// turn the display on with no cursor or blinking default
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
display();
// clear it off
clear();
// Initialize to default text direction (for roman languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);
home();
}
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear() {
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
#if defined(USE_FAST_TIMING)
delayMicroseconds(1500); // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK
#else
delayMicroseconds(2000); // this command takes a long time!
#endif
if (_oled)
setCursor(0, 0);
}
void LiquidCrystal_I2C::home() {
command(LCD_RETURNHOME); // set cursor position to zero
delayMicroseconds(2000); // this command takes a long time!
}
void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) {
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if (row > _numlines) {
row = _numlines - 1; // we count rows starting w/0
}
command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
_displaycontrol &= ~LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
_displaycontrol |= LCD_DISPLAYON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
_displaycontrol &= ~LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
_displaycontrol |= LCD_CURSORON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
_displaycontrol &= ~LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
_displaycontrol |= LCD_BLINKON;
command(LCD_DISPLAYCONTROL | _displaycontrol);
}
// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}
// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
_displaymode |= LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
_displaymode &= ~LCD_ENTRYLEFT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
command(LCD_ENTRYMODESET | _displaymode);
}
// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i = 0; i < 8; i++) {
write(charmap[i]);
}
}
//createChar with PROGMEM input
void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i = 0; i < 8; i++) {
write(pgm_read_byte_near(charmap++));
}
}
// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
_backlightval = LCD_NOBACKLIGHT;
expanderWrite(0);
}
void LiquidCrystal_I2C::backlight(void) {
_backlightval = LCD_BACKLIGHT;
expanderWrite(0);
}
/*********** mid level commands, for sending data/cmds */
inline void LiquidCrystal_I2C::command(uint8_t value) {
send(value, 0);
}
/************ low level data pushing commands **********/
// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
uint8_t highnib = value & 0xf0;
uint8_t lownib = (value << 4) & 0xf0;
write4bits((highnib) | mode);
write4bits((lownib) | mode);
}
void LiquidCrystal_I2C::write4bits(uint8_t value) {
expanderWrite(value);
pulseEnable(value);
}
void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
#if defined(USE_SOFT_I2C_MASTER)
i2c_write_byte(_Addr << 1, _data | _backlightval);
#else
Wire.beginTransmission(_Addr);
Wire.write((int )(_data) | _backlightval);
Wire.endTransmission();
#endif
}
void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
expanderWrite(_data | En); // En high
#if !defined(USE_FAST_TIMING)
delayMicroseconds(1); // enable pulse must be > 450ns // AJ 20.9.23 not required for my LCD's
#endif
expanderWrite(_data & ~En); // En low
#if !defined(USE_FAST_TIMING)
delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's
#endif
}
// Alias functions
void LiquidCrystal_I2C::cursor_on() {
cursor();
}
void LiquidCrystal_I2C::cursor_off() {
noCursor();
}
void LiquidCrystal_I2C::blink_on() {
blink();
}
void LiquidCrystal_I2C::blink_off() {
noBlink();
}
void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) {
createChar(char_num, rows);
}
void LiquidCrystal_I2C::setBacklight(uint8_t new_val) {
if (new_val) {
backlight(); // turn backlight on
} else {
noBacklight(); // turn backlight off
}
}
void LiquidCrystal_I2C::printstr(const char c[]) {
//This function is not identical to the function used for "real" I2C displays
//it's here so the user sketch doesn't have to be changed
print(c);
}
// unsupported API functions
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
void LiquidCrystal_I2C::off() {
}
void LiquidCrystal_I2C::on() {
}
void LiquidCrystal_I2C::setDelay(int cmdDelay, int charDelay) {
}
uint8_t LiquidCrystal_I2C::status() {
return 0;
}
uint8_t LiquidCrystal_I2C::keypad() {
return 0;
}
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype) {
return 0;
}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end) {
}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end) {
}
void LiquidCrystal_I2C::setContrast(uint8_t new_val) {
}
#pragma GCC diagnostic pop
#endif // _LIQUID_CRYSTAL_I2C_HPP
================================================
FILE: examples/AllProtocols/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/Callback/Callback.ino
================================================
/*
* Callback.cpp
*
* Uses a callback function which is called every time a complete IR command was received.
* This example additionally filters commands from a remote control named WM010 sending NEC commands
*
* Copyright (C) 2019-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h"
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - needs some FLASH. Must before #include
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality
// Enables protocols manually
//#define IRMP_SUPPORT_SIRCS_PROTOCOL 1
#define IRMP_SUPPORT_NEC_PROTOCOL 1
//#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1
//#define IRMP_SUPPORT_JVC_PROTOCOL 1
//#define IRMP_SUPPORT_NEC16_PROTOCOL 1
//#define IRMP_SUPPORT_NEC42_PROTOCOL 1
//#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1
//#define IRMP_SUPPORT_DENON_PROTOCOL 1
//#define IRMP_SUPPORT_RC5_PROTOCOL 1
//#define IRMP_SUPPORT_RC6_PROTOCOL 1
//#define IRMP_SUPPORT_IR61_PROTOCOL 1
//#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1
//#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1
//#define IRMP_SUPPORT_NOKIA_PROTOCOL 1
/*
* After setting the modifiers we can include the code.
*/
#include
IRMP_DATA irmp_data;
#define PROCESS_IR_RESULT_IN_MAIN_LOOP
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
volatile bool sIRDataJustReceived = false;
#endif
void handleReceivedIRData();
void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
//Enable auto resume and pass it the address of your extra buffer
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN
irmp_register_complete_callback_function(&handleReceivedIRData);
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
}
void loop()
{
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
if (sIRDataJustReceived)
{
sIRDataJustReceived = false;
evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
irmp_result_print(&irmp_data); // this is not allowed in ISR context for any kind of RTOS
}
#endif
/*
* Put your code here
*/
}
/*
* Callback function
* Here we know, that data is available.
* This function is executed in ISR (Interrupt Service Routine) context (interrupts are blocked here).
* Make it short and fast and keep in mind, that you can not use delay(), prints longer than print buffer size etc.,
* because they require interrupts enabled to return.
* In order to enable other interrupts you can call sei() (enable interrupt again) after evaluating/copying data.
* Good practice, but somewhat more complex, is to copy relevant data and signal receiving to main loop.
*/
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void handleReceivedIRData()
{
irmp_get_data(&irmp_data);
#if !defined(ARDUINO_ARCH_MBED)
interrupts(); // enable interrupts
#endif
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
/*
* Set flag to trigger printing of results in main loop,
* since printing should not be done in a callback function
* running in ISR (Interrupt Service Routine) context where interrupts are disabled.
*/
sIRDataJustReceived = true;
#else
interrupts(); // enable interrupts
evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
irmp_result_print(&irmp_data); // This is not recommended, but simpler and works, except for any kind of RTOS like on ESP and MBED.
#endif
}
void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags)
{
/*
* Filter for commands from the WM010 IR Remote
*/
if (aAddress == 0xF708)
{
/*
* Skip repetitions of command
*/
if (!(aAddress & IRMP_FLAG_REPETITION))
{
/*
* Evaluation of IR command
*/
switch (aAddress)
{
case 0x48:
digitalWrite(LED_BUILTIN, HIGH);
break;
case 0x0B:
digitalWrite(LED_BUILTIN, LOW);
break;
default:
break;
}
}
}
}
================================================
FILE: examples/Callback/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/IRDispatcherDemo/DemoIRCommandMapping.h
================================================
/*
* DemoIRCommandMapping.h
*
* Contains IR remote button codes, strings, and the mapping of codes to functions to call by the dispatcher
*
* Copyright (C) 2019-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef _IR_COMMAND_MAPPING_H
#define _IR_COMMAND_MAPPING_H
#include
#include "IRCommandDispatcher.h" // IRToCommandMappingStruct, IR_COMMAND_FLAG_BLOCKING etc. are defined here
/*
* !!! Choose your remote !!!
*/
//#define USE_KEYES_REMOTE_CLONE With number pad and direction control swapped, will be taken as default
//#define USE_KEYES_REMOTE
#if !defined(USE_KEYES_REMOTE) && !defined(USE_KEYES_REMOTE_CLONE)
#define USE_KEYES_REMOTE_CLONE // the one you can buy at Aliexpress
#endif
#if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE))
#error "Please choose only one remote for compile"
#endif
#if defined(USE_KEYES_REMOTE_CLONE)
#define IR_REMOTE_NAME "KEYES_CLONE"
// Codes for the KEYES CLONE remote control with 17 keys with number pad above direction control
#define IR_ADDRESS 0x00
#define IR_UP 0x18
#define IR_DOWN 0x52
#define IR_RIGHT 0x5A
#define IR_LEFT 0x08
#define IR_OK 0x1C
#define IR_1 0x45
#define IR_2 0x46
#define IR_3 0x47
#define IR_4 0x44
#define IR_5 0x40
#define IR_6 0x43
#define IR_7 0x07
#define IR_8 0x15
#define IR_9 0x09
#define IR_0 0x19
#define IR_STAR 0x16
#define IR_HASH 0x0D
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_START IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_RESET IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE1 IR_1
#define COMMAND_TONE2 IR_2
#define COMMAND_TONE3 IR_3
//#define IR_4
//#define IR_5
//#define IR_6
//#define IR_7
//#define IR_8
//#define IR_9
#endif
#if defined(USE_KEYES_REMOTE)
#define IR_REMOTE_NAME "KEYES"
/*
* FIRST:
* IR code to button mapping for better reading. IR codes should only referenced here.
*/
// Codes for the KEYES remote control with 17 keys and direction control above number pad
#define IR_ADDRESS 0x00
#define IR_UP 0x46
#define IR_DOWN 0x15
#define IR_RIGHT 0x43
#define IR_LEFT 0x44
#define IR_OK 0x40
#define IR_1 0x16
#define IR_2 0x19
#define IR_3 0x0D
#define IR_4 0x0C
#define IR_5 0x18
#define IR_6 0x5E
#define IR_7 0x08
#define IR_8 0x1C
#define IR_9 0x5A
#define IR_0 0x52
#define IR_STAR 0x42
#define IR_HASH 0x4A
/*
* SECOND:
* IR button to command mapping for better reading. IR buttons should only referenced here.
*/
#define COMMAND_ON IR_UP
#define COMMAND_OFF IR_DOWN
#define COMMAND_INCREASE_BLINK IR_RIGHT
#define COMMAND_DECREASE_BLINK IR_LEFT
#define COMMAND_RESET IR_OK
#define COMMAND_STOP IR_HASH
#define COMMAND_STOP IR_STAR
#define COMMAND_BLINK IR_0
#define COMMAND_TONE2 IR_1
#define COMMAND_TONE1 IR_2
#define COMMAND_TONE2 IR_3
#define COMMAND_TONE2 IR_4
#define COMMAND_TONE2 IR_5
#define COMMAND_TONE2 IR_6
#define COMMAND_TONE2 IR_7
#define COMMAND_TONE2 IR_8
#define COMMAND_TONE2 IR_9
#endif
/*
* THIRD:
* Main mapping of commands to C functions
*/
// Strings of commands for Serial output
static const char LEDon[] PROGMEM ="LED on";
static const char LEDoff[] PROGMEM ="LED off";
static const char blink20times[] PROGMEM ="blink 20 times";
static const char blinkStart[] PROGMEM ="blink start";
static const char increaseBlink[] PROGMEM ="increase blink frequency";
static const char decreaseBlink[] PROGMEM ="decrease blink frequency";
static const char tone2200[] PROGMEM ="tone 2200";
static const char tone1800[] PROGMEM ="tone 1800";
static const char printMenu[] PROGMEM ="printMenu";
static const char reset[] PROGMEM ="reset";
static const char stop[] PROGMEM ="stop";
/*
* Main mapping array of commands to C functions and command strings
* The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled
*/
const struct IRToCommandMappingStruct IRMapping[] = { /**/
{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, /**/
{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, /* */
/*
* Short commands that can always be executed, but must be able to terminate other blocking commands (only doLedBlink20times() in this example)
*/
{ COMMAND_START, IR_COMMAND_FLAG_BLOCKING, &doLedBlinkStart, COMMAND_STRING(blinkStart) }, /**/
{ COMMAND_ON, IR_COMMAND_FLAG_BLOCKING, &doLedOn, COMMAND_STRING(LEDon) }, /**/
{ COMMAND_OFF, IR_COMMAND_FLAG_BLOCKING, &doLedOff, COMMAND_STRING(LEDoff) }, /**/
/*
* Short commands that can always be executed
*/
{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, COMMAND_STRING(tone1800) }, /* Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled */
{ COMMAND_TONE3, IR_COMMAND_FLAG_NON_BLOCKING, &doPrintMenu, COMMAND_STRING(printMenu) }, /**/
{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, COMMAND_STRING(reset) },
/*
* Repeatable short commands
*/
{ COMMAND_TONE2, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doTone2200, COMMAND_STRING(tone2200) }, /* Lasts 50 ms and allows receiving of repeats */
{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, COMMAND_STRING(increaseBlink) }, /**/
{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, COMMAND_STRING(decreaseBlink) } };
#endif // _IR_COMMAND_MAPPING_H
================================================
FILE: examples/IRDispatcherDemo/IRDispatcherDemo.ino
================================================
/*
* IRDispatcherDemo.cpp
*
* Example how to use IRCommandDispatcher to receive IR commands and map them to different actions / functions by means of a mapping array.
*
* Copyright (C) 2020-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Choose the library to be used for IR receiving
*/
//#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
//#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding
//#define USE_IRMP_LIBRARY // The IRMP library is used for decoding
//#define DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT // Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry.
#define NO_LED_FEEDBACK_CODE // We use LED_BUILTIN for command feedback and therefore cannot use is as IR receiving feedback
#define INFO // To see some informative output of the IRCommandDispatcher library
//#define DEBUG // To see some additional debug output of the IRCommandDispatcher library
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if defined(INFO) || defined(DEBUG)
#define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries.
#endif
#if defined(TONE_PIN)
#define DISPATCHER_BUZZER_FEEDBACK_PIN TONE_PIN // The pin to be used for the optional 50 ms buzzer feedback before executing a command. Only available for TinyIR.
#endif
#if defined(USE_IRMP_LIBRARY)
//Enable protocols for IRMP
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1
//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory
#endif // defined(USE_IRMP_LIBRARY)
bool doBlink = false;
uint16_t sBlinkDelay = 200;
/*
* The functions which are called by the IR commands.
* They must be declared before including DemoIRCommandMapping.h, where the mapping to IR keys is defined.
*/
void doPrintMenu();
void doLedOn();
void doLedOff();
void doIncreaseBlinkFrequency();
void doDecreaseBlinkFrequency();
void doStop();
void doResetBlinkFrequency();
void doLedBlinkStart();
void doLedBlink20times();
void doTone1800();
void doTone2200();
/*
* Set definitions and include IRCommandDispatcher library after the declaration of all commands required for mapping
*/
#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IRMapping array, IR_ADDRESS etc.
#include "IRCommandDispatcher.hpp" // This can optionally set USE_TINY_IR_RECEIVER
void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver library version " VERSION_TINYIR));
#elif defined(USE_IRREMOTE_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRremote library version " VERSION_IRREMOTE));
#elif defined(USE_IRMP_LIBRARY)
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRMP library version " VERSION_IRMP));
#endif
#if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN)
// play feedback tone before IRDispatcher.init(), because it kills the IR timer settings, which are made by init()
tone(TONE_PIN, 1000, 50);
delay(50);
#endif
IRDispatcher.init(); // This calls the init function of the chosen library
IRDispatcher.printIRInfo(&Serial);
doPrintMenu();
#if defined(DEBUG) && defined(SP)
Serial.print(F("SP=0x"));
Serial.println(SP, HEX);
#endif
}
void loop()
{
IRDispatcher.checkAndRunSuspendedBlockingCommands();
if (doBlink)
{
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
}
if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000)
{
// Short beep as remainder, if we did not receive any command in the last 2 minutes
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
doTone1800();
#if defined(INFO)
Serial.println(F("2 minutes timeout"));
#endif
}
// delay(10);
}
/*
* Menu for simple China Keyes or Keyes clone IR controls with number pad and direction control pad
*/
void doPrintMenu()
{
Serial.println();
Serial.println(F("Press 1 for tone 1800 Hz"));
Serial.println(F("Press 2 for tone 2200 Hz"));
Serial.println(F("Press 3 for this Menu"));
Serial.println(F("Press 0 for LED blink 20 times"));
Serial.println(F("Press UP for LED on"));
Serial.println(F("Press DOWN for LED off"));
Serial.println(F("Press OK for LED blink start"));
Serial.println(F("Press RIGHT for LED increase blink frequency"));
Serial.println(F("Press LEFT for LED decrease blink frequency"));
Serial.println(F("Press STAR for reset blink frequency"));
Serial.println(F("Press HASH for stop"));
Serial.println();
}
/*
* Here the actions that are matched to IR keys
*/
void doLedOn()
{
digitalWrite(LED_BUILTIN, HIGH);
doBlink = false;
}
void doLedOff()
{
digitalWrite(LED_BUILTIN, LOW);
doBlink = false;
}
void doIncreaseBlinkFrequency()
{
doBlink = true;
if (sBlinkDelay > 5)
{
sBlinkDelay -= sBlinkDelay / 4;
}
}
void doDecreaseBlinkFrequency()
{
doBlink = true;
sBlinkDelay += sBlinkDelay / 4;
}
void doStop()
{
doBlink = false;
digitalWrite(LED_BUILTIN, LOW);
}
void doResetBlinkFrequency()
{
sBlinkDelay = 200;
digitalWrite(LED_BUILTIN, LOW);
}
void doLedBlinkStart()
{
doBlink = true;
}
/*
* This is a blocking function which checks for stop
*/
void doLedBlink20times()
{
for (int i = 0; i < 20; ++i)
{
digitalWrite(LED_BUILTIN, HIGH);
DELAY_AND_RETURN_IF_STOP(200);
digitalWrite(LED_BUILTIN, LOW);
DELAY_AND_RETURN_IF_STOP(200);
}
}
/*
* Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled
*/
void doTone1800()
{
#if defined(TONE_PIN)
IRremoteTone(TONE_PIN, 1800, 200);
#endif
}
/*
* Lasts 50 ms and allows receiving of repeats
*/
void doTone2200()
{
#if defined(TONE_PIN)
IRremoteTone(TONE_PIN, 2200, 50);
#endif
}
/*
* Convenience IR library wrapper function for Arduino tone()
* It currently disables the receiving of repeats
* It is not part of the library because it statically allocates the tone interrupt vector 7.
*/
void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration)
{
// IRMP_ENABLE_PIN_CHANGE_INTERRUPT currently disables the receiving of repeats
#if defined(ESP8266) || defined(NRF5) || defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
(void) aTonePin;
(void) aFrequency;
(void) aDuration;
return;
#else
/*
* Stop receiver, generate a single beep and start receiver again
*/
# if defined(ESP32) || defined(USE_TINY_IR_RECEIVER )// ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too.
tone(aTonePin, aFrequency, aDuration);
# else
# if defined(USE_IRREMOTE_LIBRARY)
IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
# else
storeIRTimer();
# endif
tone(aTonePin, aFrequency, 0);
if (aDuration == 0)
{
aDuration = 100;
}
delay(aDuration);
noTone(aTonePin);
# if defined(USE_IRREMOTE_LIBRARY)
IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
# else
restoreIRTimer();
# endif
# endif
#endif
}
================================================
FILE: examples/IRDispatcherDemo/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/Interrupt/Interrupt.ino
================================================
/*
* Interrupt.cpp
*
* Receives IR protocol data by using pin change interrupts and no polling by timer.
* !!! This WILL NOT work for all protocols.!!!
* Tested for NEC, Kaseiko, Denon, RC6, Samsung + Samsg32.
*
* To disable one of them or to enable other protocols, specify this before the "#include " line.
* If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example).
* The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example).
*
* Copyright (C) 2019-2022 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h"
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - needs some FLASH. Must before #include
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality
#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irmp_data;
#define PROCESS_IR_RESULT_IN_MAIN_LOOP
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
volatile bool sIRDataJustReceived = false;
#endif
void handleReceivedIRData();
void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags);
void setup() {
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN
irmp_register_complete_callback_function(&handleReceivedIRData);
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
}
void loop() {
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
if (sIRDataJustReceived) {
sIRDataJustReceived = false;
evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
irmp_result_print(&irmp_data); // this is not allowed in ISR context for any kind of RTOS
}
#endif
/*
* Put your code here
*/
}
/*
* Callback function
* Here we know, that data is available.
* This function is executed in ISR (Interrupt Service Routine) context (interrupts are blocked here).
* Make it short and fast and keep in mind, that you can not use delay(), prints longer than print buffer size etc.,
* because they require interrupts enabled to return.
* In order to enable other interrupts you can call sei() (enable interrupt again) after evaluating/copying data.
* Good practice, but somewhat more complex, is to copy relevant data and signal receiving to main loop.
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR handleReceivedIRData()
#else
void handleReceivedIRData()
#endif
{
irmp_get_data(&irmp_data);
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
/*
* Set flag to trigger printing of results in main loop,
* since printing should not be done in a callback function
* running in ISR (Interrupt Service Routine) context where interrupts are disabled.
*/
sIRDataJustReceived = true;
#else
interrupts(); // enable interrupts
evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
irmp_result_print(&irmp_data); // This is not recommended, but simpler and works, except for any kind of RTOS like on ESP and MBED.
#endif
}
void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags)
{
/*
* Filter for commands from the WM010 IR Remote
*/
if (aAddress == 0xF708)
{
/*
* Skip repetitions of command
*/
if (!(aAddress & IRMP_FLAG_REPETITION))
{
/*
* Evaluation of IR command
*/
switch (aAddress)
{
case 0x48:
digitalWrite(LED_BUILTIN, HIGH);
break;
case 0x0B:
digitalWrite(LED_BUILTIN, LOW);
break;
default:
break;
}
}
}
}
================================================
FILE: examples/Interrupt/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/OneProtocol/OneProtocol.ino
================================================
/*
* OneProtocol.cpp
*
* Receives IR protocol data. Only one protocol is activated.
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h" // Sets input pin to 3
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
//#define IRMP_SUPPORT_SIRCS_PROTOCOL 1
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // includes APPLE and ONKYO protocols
//#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1
//#define IRMP_SUPPORT_JVC_PROTOCOL 1
//#define IRMP_SUPPORT_NEC16_PROTOCOL 1
//#define IRMP_SUPPORT_NEC42_PROTOCOL 1
//#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1
//#define IRMP_SUPPORT_DENON_PROTOCOL 1
//#define IRMP_SUPPORT_RC5_PROTOCOL 1
//#define IRMP_SUPPORT_RC6_PROTOCOL 1
//#define IRMP_SUPPORT_IR61_PROTOCOL 1
//#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1
//#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1
//#define IRMP_SUPPORT_NOKIA_PROTOCOL 1
// use F_INTERRUPTS=20000 for Support of LEGO and RCMM
//#define F_INTERRUPTS 20000 // interrupts per second, 50us, min: 10000, max: 20000, typ: 15000
//#define IRMP_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes
//#define IRMP_SUPPORT_RCMM_PROTOCOL 1 // RCMM 12,24, or 32 >= 20000 ~150 bytes
/*
* Protocols which are not enabled in the irmpSelectAllProtocols.h for the AllProtocol example
*/
//#define IRMP_SUPPORT_FAN_PROTOCOL 1 // FAN (ventilator) >= 10000 ~50 bytes conflicts with NUBERT
//#define IRMP_SUPPORT_ORTEK_PROTOCOL 1 // ORTEK (Hama) >= 10000 ~150 bytes conflicts with FDC and NETBOX
//#define IRMP_SUPPORT_ROOMBA_PROTOCOL 1 // iRobot Roomba >= 10000 ~150 bytes conflicts with RC6
//#define IRMP_SUPPORT_RUWIDO_PROTOCOL 1 // RUWIDO, T-Home >= 15000 ~550 bytes conflicts with DENON
//#define IRMP_SUPPORT_S100_PROTOCOL 1 // S100 >= 10000 ~250 bytes conflicts with RC5
//#define IRMP_SUPPORT_ACP24_PROTOCOL 1 // ACP24 >= 10000 ~250 bytes conflicts with DENON
//#define IRMP_SUPPORT_PANASONIC_PROTOCOL 1 // PANASONIC Beamer >= 10000 ~250 bytes conflicts with KASEIKYO
//#define IRMP_SUPPORT_RCII_PROTOCOL 1 // RCII T+A >= 15000 ~250 bytes conflicts with GRUNDIG and NOKIA
/*
* More protocol definitions can be found in irmpSelectAllProtocols.h
*/
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irmp_data;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
// Wait until Serial Monitor is attached.
// Required for boards using USB code for Serial like Leonardo.
// Is void for USB Serial implementations using external chips e.g. a CH340.
while (!Serial)
;
// !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irmp_init();
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN
}
void loop()
{
/*
* Check if new data available and get them
*/
if (irmp_get_data(&irmp_data))
{
/*
* Here data is available -> evaluate IR command
*/
switch (irmp_data.command)
{
case 0x48:
case 0x40:
Serial.println(F("Received right code and do something"));
digitalWrite(LED_BUILTIN, HIGH);
break;
default:
break;
}
irmp_result_print(&irmp_data);
}
}
================================================
FILE: examples/OneProtocol/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/RFProtocols/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/RFProtocols/RFProtocols.ino
================================================
/*
* RFProtocols.cpp
*
* Receives 2 RF protocol (433 MHz) data.
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h" // Sets input pin to 3
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#include // This enables all possible RF protocols - currently 2 protocols
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irmp_data;
void setup()
{
// initialize the digital pin as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
// Wait until Serial Monitor is attached.
// Required for boards using USB code for Serial like Leonardo.
// Is void for USB Serial implementations using external chips e.g. a CH340.
while (!Serial)
;
// !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
#if defined(ESP8266)
Serial.println();
#endif
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN - commented out, since we use built in LED in loop below
Serial.print(F("Ready to receive RF (433 MHz) signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
}
void loop()
{
/*
* Check if new data available and get them
*/
if (irmp_get_data(&irmp_data))
{
irmp_result_print(&irmp_data);
}
}
================================================
FILE: examples/ReceiveAndSend/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/ReceiveAndSend/ReceiveAndSend.ino
================================================
/*
* ReceiveAndSend.cpp
*
* Serves as a IR remote macro expander
* Receives Samsung32 protocol and on receiving a specified input frame,
* it sends multiple Samsung32 frames with appropriate delays in between.
* This serves as a Netflix-key emulation for my old Samsung H5273 TV.
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// ATMEL ATTINY85
// Piezo speaker must have a 270 ohm resistor in series for USB programming and running at the Samsung TV.
// IR LED has a 270 ohm resistor in series.
// +-\/-+
// !RESET (5) PB5 1| |8 Vcc
// USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output
// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED
// GND 4| |5 PB0 (0) IR Input
// +----+
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone
* -----------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0 4 3
* ATtin167 9 8 5 // Digispark pro number schema
* ATtin167 3 2 7
* SAMD21 3 4 5
* ESP8266 14 // D5 12 // D6 %
* ESP32 15 4 %
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
*/
#include
/*
* First define macros for input and output pin etc.
*/
#include "PinDefinitionsAndMore.h"
//#define IR_OUTPUT_IS_ACTIVE_LOW
#define IRSND_IR_FREQUENCY 38000
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1
/*
* After setting the definitions we can include the code and compile it.
*/
#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND // otherwise we get an error on AVR platform: redefinition of 'void __vector_8()
#include
#include
IRMP_DATA irmp_data;
IRMP_DATA irsnd_data;
void sendSamsungSmartHubMacro(bool aDoSelect);
void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
// tone before IR setup, since it kills the IR timer settings
tone(TONE_PIN, 2200);
digitalWrite(LED_BUILTIN, HIGH);
delay(400);
digitalWrite(LED_BUILTIN, LOW);
noTone(TONE_PIN);
irmp_init();
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN for receive and send
irsnd_init();
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
Serial.println(F("Ready to send IR signals at pin " STR(IRSND_OUTPUT_PIN)));
irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL;
irsnd_data.address = 0x0707;
irsnd_data.flags = 1; // repeat frame 1 time
}
void loop()
{
/*
* Check if new data available and get them
*/
if (irmp_get_data(&irmp_data))
{
irmp_result_print(&irmp_data);
/*
* Here data is available -> evaluate IR command
*/
switch (irmp_data.command)
{
case 0xB847: // The play key on the bottom of my Samsung remote
Serial.println(F("Play key detected, open Netflix"));
sendSamsungSmartHubMacro(true);
break;
case 0xB54A: // The pause key on the bottom of my Samsung remote
Serial.println(F("Pause key detected, open SmartHub"));
sendSamsungSmartHubMacro(false);
break;
default:
break;
}
// Flush repeats received
irmp_get_data(&irmp_data);
}
}
void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis)
{
irsnd_data.command = aCommand; // For my Samsung, the high byte is the inverse of the low byte, this is not checked here.
// true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending.
if (!irsnd_send_data(&irsnd_data, true))
{
Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print()
}
irsnd_data_print(&Serial,&irsnd_data);
delay(aDelayMillis);
}
bool sMacroWasCalledBefore = false;
#define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error
#define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed
/*
* This macro calls the last SmartHub application you selected manually
*
* @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu
*
*/
void sendSamsungSmartHubMacro(bool aDoSelect)
{
uint32_t tWaitTimeAfterBoot;
if (aDoSelect)
{
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS;
}
else
{
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS;
}
if (millis() < tWaitTimeAfterBoot)
{
// division by 1000 and printing requires much (8%) program memory
Serial.print(F("It is "));
Serial.print(millis() / 1000);
Serial.print(F(" seconds after boot, Samsung H5273 TV requires "));
Serial.print(tWaitTimeAfterBoot / 1000);
Serial.println(F(" seconds after boot to be ready for the command"));
tone(TONE_PIN, 2200);
delay(100);
noTone(TONE_PIN);
delay(100);
tone(TONE_PIN, 2200);
delay(100);
noTone(TONE_PIN);
while (millis() < tWaitTimeAfterBoot)
{
delay(10); // blocking wait
}
}
// Do beep feedback for special key to be received
tone(TONE_PIN, 2200);
delay(200);
noTone(TONE_PIN);
irmp_init(); // restore timer for IR receive after using of tone
Serial.println(F("Wait for \"not supported\" to disappear"));
delay(2000);
Serial.println(F("Start sending of Samsung IR macro"));
IRSendWithDelay(0xE51A, 2000); // Menu and wait for the Menu to pop up
Serial.println(F("Wait for the menu to pop up"));
if (!sMacroWasCalledBefore)
{
delay(2000); // wait additional time for the Menu load
}
for (uint_fast8_t i = 0; i < 4; ++i)
{
IRSendWithDelay(0x9E61, 250); // Down arrow. For my Samsung, the high byte of the command is the inverse of the low byte
}
IRSendWithDelay(0x9D62, 400); // Right arrow
for (uint_fast8_t i = 0; i < 2; ++i)
{
IRSendWithDelay(0x9E61, 250); // Down arrow
}
delay(250);
IRSendWithDelay(0x9768, 1); // Enter for SmartHub
if (aDoSelect)
{
Serial.println(F("Wait for SmartHub to show up, before entering current application"));
delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears
IRSendWithDelay(0x9768, 1); // Enter for last application (e.g. Netflix or Amazon)
}
sMacroWasCalledBefore = true;
Serial.println(F("Done"));
}
================================================
FILE: examples/ReceiveAndSendDynamicPins/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/ReceiveAndSendDynamicPins/ReceiveAndSendDynamicPins.ino
================================================
/*
* ReceiveAndSendDynamicPins.cpp
*
* Example how to use pins specified at runtime.
*
* Serves as a IR remote macro expander
* Receives Samsung32 protocol and on receiving a specified input frame, it sends multiple Samsung32 frames.
* This serves as a Netflix-key emulation for my old Samsung H5273 TV.
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// ATMEL ATTINY85
// Piezo speaker must have a 270 ohm resistor in series for USB programming and running at the Samsung TV.
// IR LED has a 270 ohm resistor in series.
// +-\/-+
// !RESET (5) PB5 1| |8 Vcc
// USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output
// USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED
// GND 4| |5 PB0 (0) IR Input
// +----+
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone
* -----------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0 4 3
* ATtin167 9 8 5 // Digispark pro number schema
* ATtin167 3 2 7
* SAMD21 3 4 5
* ESP8266 14 // D5 12 // D6 %
* ESP32 15 4 %
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
*/
/*
* Allow dynamic specification of input and output pins.
* Requires additional 200 bytes program memory.
* This must be first, it is used in PinDefinitionsAndMore.h
*/
#define IRMP_IRSND_ALLOW_DYNAMIC_PINS
#include
/*
* Set library modifiers first to set input and output pin etc.
*/
#include "PinDefinitionsAndMore.h"
//#define IR_OUTPUT_IS_ACTIVE_LOW
#define IRSND_IR_FREQUENCY 38000
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1
/*
* After setting the definitions we can include the code and compile it.
*/
#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND // otherwise we get an error on AVR platform: redefinition of 'void __vector_8()
#include
#include
IRMP_DATA irmp_data;
uint8_t sIRMPInputPin;
IRMP_DATA irsnd_data;
void sendSamsungSmartHubMacro(bool aDoSelect);
void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis);
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
tone(TONE_PIN, 2200);
digitalWrite(LED_BUILTIN, HIGH);
delay(400);
digitalWrite(LED_BUILTIN, LOW);
noTone(TONE_PIN);
/*
* Request pin number from user by serial monitor
*/
Serial.println(F("Please enter pin number to use for receiving IR signals."));
while (Serial.available() == 0)
{
; // Wait for user response
}
sIRMPInputPin = Serial.parseInt();
while (Serial.available())
{
Serial.read(); // read rest of line and CR/LF from buffer to enable for next input
}
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin "));
Serial.println(sIRMPInputPin);
irmp_init(sIRMPInputPin, LED_BUILTIN); // Enable receive signal feedback at LED_BUILTIN for receive (and send)
Serial.println(F("Please enter pin number to use for sending IR signals."));
while (Serial.available() == 0)
{
; // Wait for user response
}
uint8_t tIRSNDOutputPin = Serial.parseInt();
Serial.print(F("Ready to send IR signals at pin "));
Serial.println(tIRSNDOutputPin);
irsnd_init(tIRSNDOutputPin); // feedback LED is specified at irmp_init()
irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL;
irsnd_data.address = 0x0707;
irsnd_data.flags = 1; // repeat frame 1 time
}
void loop()
{
/*
* Check if new data available and get them
*/
if (irmp_get_data(&irmp_data))
{
irmp_result_print(&irmp_data);
/*
* Here data is available -> evaluate IR command
*/
switch (irmp_data.command)
{
case 0xB847: // The play key on the bottom of my Samsung remote
Serial.println(F("Play key detected, open Netflix"));
sendSamsungSmartHubMacro(true);
break;
case 0xB54A: // The pause key on the bottom of my Samsung remote
Serial.println(F("Pause key detected, open SmartHub"));
sendSamsungSmartHubMacro(false);
break;
default:
break;
}
// Flush repeats received
irmp_get_data(&irmp_data);
}
}
void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis)
{
irsnd_data.command = aCommand;
// true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending.
if (!irsnd_send_data(&irsnd_data, true))
{
Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print()
}
irsnd_data_print(&Serial,&irsnd_data);
delay(aDelayMillis);
}
bool sMacroWasCalledBefore = false;
#define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error
#define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed
/*
* This macro calls the last SmartHub application you selected manually
*
* @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu
*
*/
void sendSamsungSmartHubMacro(bool aDoSelect)
{
uint32_t tWaitTimeAfterBoot;
if (aDoSelect)
{
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS;
}
else
{
tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS;
}
if (millis() < tWaitTimeAfterBoot)
{
// division by 1000 and printing requires much (8%) program memory
Serial.print(F("It is "));
Serial.print(millis() / 1000);
Serial.print(F(" seconds after boot, Samsung H5273 TV requires "));
Serial.print(tWaitTimeAfterBoot / 1000);
Serial.println(F(" seconds after boot to be ready for the command"));
tone(TONE_PIN, 2200);
delay(100);
noTone(TONE_PIN);
delay(100);
tone(TONE_PIN, 2200);
delay(100);
noTone(TONE_PIN);
while (millis() < tWaitTimeAfterBoot)
{
delay(10); // blocking wait
}
}
// Do beep feedback for special key to be received
tone(TONE_PIN, 2200);
delay(200);
noTone(TONE_PIN);
irmp_init(sIRMPInputPin); // restore timer for IR receive after using of tone
Serial.println(F("Wait for \"not supported\" to disappear"));
delay(2000);
Serial.println(F("Start sending of Samsung IR macro"));
IRSendWithDelay(0xE51A, 2000); // Menu and wait for the Menu to pop up
Serial.println(F("Wait for the menu to pop up"));
if (!sMacroWasCalledBefore)
{
delay(2000); // wait additional time for the Menu load
}
for (uint_fast8_t i = 0; i < 4; ++i)
{
IRSendWithDelay(0x9E61, 250); // Down arrow
}
IRSendWithDelay(0x9D62, 400); // Right arrow
for (uint_fast8_t i = 0; i < 2; ++i)
{
IRSendWithDelay(0x9E61, 250); // Down arrow
}
delay(250);
IRSendWithDelay(0x9768, 1); // Enter for SmartHub
if (aDoSelect)
{
Serial.println(F("Wait for SmartHub to show up, before entering current application"));
delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears
IRSendWithDelay(0x9768, 1); // Enter for last application (e.g. Netflix or Amazon)
}
sMacroWasCalledBefore = true;
Serial.println(F("Done"));
}
================================================
FILE: examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
================================================
/*
* ReceiverTimingAnalysis.cpp
*
* This program enables the pin change interrupt at pin 3 and waits for NEC (or other Pulse-Distance-Coding) IR Signal.
* It measures the pulse and pause times of the incoming signal and computes some statistics for it.
*
* Observed values:
* Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level.
* VS1838 Mark Excess -50 to +50 us
* TSOP31238 Mark Excess 0 to +50
*
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
#define IR_RECEIVE_PIN 2
//#define IR_RECEIVE_PIN 3
// Helper macro for getting a macro definition as string
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
#if !(defined(EICRA) && defined(EIFR) && defined(EIMSK))
void measureTimingISR(void);
#endif
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
// Wait until Serial Monitor is attached.
// Required for boards using USB code for Serial like Leonardo.
// Is void for USB Serial implementations using external chips e.g. a CH340.
while (!Serial)
;
// !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__));
#if defined(EICRA) && defined(EIFR) && defined(EIMSK)
# if (IR_RECEIVE_PIN == 2)
EICRA |= _BV(ISC00); // interrupt on any logical change
EIFR |= _BV(INTF0); // clear interrupt bit
EIMSK |= _BV(INT0); // enable interrupt on next change
# elif (IR_RECEIVE_PIN == 3)
EICRA |= _BV(ISC10); // enable interrupt on pin3 on both edges for ATmega328
EIFR |= _BV(INTF1); // clear interrupt bit
EIMSK |= _BV(INT1); // enable interrupt on next change
# endif
#else
# if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
attachInterrupt(IR_RECEIVE_PIN, measureTimingISR, CHANGE);
# else
attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE); // CHANGE can also be an enum :-(
# endif
#endif
Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN)));
Serial.println();
}
uint8_t ISREdgeCounter = 0;
volatile uint32_t LastMicros;
struct timingStruct {
uint16_t minimum;
uint8_t indexOfMinimum;
uint16_t maximum;
uint8_t indexOfMaximum;
uint16_t average;
uint16_t SumForAverage;
uint8_t SampleCount;
// uint8_t LastPrintedCount;
};
struct timingStruct Mark;
struct timingStruct ShortSpace;
struct timingStruct LongSpace;
/*
* Compute minimum, maximum and average
*/
void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue) {
if (aTimingStruct->SampleCount == 0) {
// initialize values
aTimingStruct->minimum = UINT16_MAX;
aTimingStruct->maximum = 0;
aTimingStruct->SumForAverage = 0;
}
if (aTimingStruct->minimum > aValue) {
aTimingStruct->minimum = aValue;
aTimingStruct->indexOfMinimum = aTimingStruct->SampleCount;
}
if (aTimingStruct->maximum < aValue) {
aTimingStruct->maximum = aValue;
aTimingStruct->indexOfMaximum = aTimingStruct->SampleCount;
}
aTimingStruct->SampleCount++;
aTimingStruct->SumForAverage += aValue;
aTimingStruct->average = (aTimingStruct->SumForAverage + (aTimingStruct->SampleCount / 2)) / aTimingStruct->SampleCount;
}
void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) {
// if (aTimingStruct->LastPrintedCount != aTimingStruct->SampleCount)
// {
// aTimingStruct->LastPrintedCount = aTimingStruct->SampleCount;
Serial.print(aCaption);
Serial.print(F(": SampleCount="));
Serial.print(aTimingStruct->SampleCount);
Serial.print(F(" Minimum="));
Serial.print(aTimingStruct->minimum);
Serial.print(F(" @"));
Serial.print(aTimingStruct->indexOfMinimum);
Serial.print(F(" Maximum="));
Serial.print(aTimingStruct->maximum);
Serial.print(F(" @"));
Serial.print(aTimingStruct->indexOfMaximum);
Serial.print(F(" Delta="));
Serial.print(aTimingStruct->maximum - aTimingStruct->minimum);
Serial.print(F(" Average="));
Serial.print(aTimingStruct->average);
Serial.println();
// }
}
void loop() {
if (Mark.SampleCount >= 32) {
/*
* This check enables statistics for longer protocols like Kaseikyo/Panasonics
*/
#if !defined(ARDUINO_ARCH_MBED)
noInterrupts();
#endif
uint32_t tLastMicros = LastMicros;
#if !defined(ARDUINO_ARCH_MBED)
interrupts();
#endif
uint32_t tMicrosDelta = micros() - tLastMicros;
if (tMicrosDelta > 10000) {
// NEC signal ended just now
Serial.println();
printTimingValues(&Mark, "Mark ");
printTimingValues(&ShortSpace, "ShortSpace");
printTimingValues(&LongSpace, "LongSpace ");
/*
* Print analysis of mark and short spaces
*/
Serial.println(F("Analysis :"));
Serial.print(F(" (Average of mark + short space)/2 = "));
int16_t MarkAndShortSpaceAverage = (Mark.average + ShortSpace.average) / 2;
Serial.print(MarkAndShortSpaceAverage);
Serial.print(F(" us\r\n Delta (to NEC standard 560) = "));
Serial.print(MarkAndShortSpaceAverage - 560);
Serial.print(F("us\r\n MARK_EXCESS_MICROS = (Average of mark - Average of mark and short space) = "));
Serial.print((int16_t) Mark.average - MarkAndShortSpaceAverage);
Serial.print(F("us"));
Serial.println();
Serial.println();
Mark.SampleCount = 0; // used as flag for not printing the results more than once
}
}
}
/*
* The interrupt handler.
* Just add to the appropriate timing structure.
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR measureTimingISR()
#else
# if defined(EICRA) && defined(EIFR) && defined(EIMSK)
# if (IR_RECEIVE_PIN == 2)
ISR(INT0_vect)
# elif (IR_RECEIVE_PIN == 3)
ISR(INT1_vect)
# endif
# else
void measureTimingISR()
# endif
#endif
{
uint32_t tMicros = micros();
uint32_t tMicrosDelta = tMicros - LastMicros;
LastMicros = tMicros;
/*
* read level and give feedback
*/
uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN);
digitalWrite(LED_BUILTIN, !tInputLevel);
if (tMicrosDelta > 10000) {
// gap > 10 ms detected, reset counter to first detected edge and initialize timing structures
ISREdgeCounter = 1;
LongSpace.SampleCount = 0;
ShortSpace.SampleCount = 0;
Mark.SampleCount = 0;
} else {
ISREdgeCounter++;
}
/*
* Skip header mark and space and first bit mark and space
*/
if (ISREdgeCounter > 4) {
if (tInputLevel != LOW) {
// Mark ended
processTmingValue(&Mark, tMicrosDelta);
// Serial.print('M');
} else {
// Space ended
if (tMicrosDelta > 1000) {
// long space - logical 1
processTmingValue(&LongSpace, tMicrosDelta);
Serial.print('1');
} else {
// short space - logical 0
processTmingValue(&ShortSpace, tMicrosDelta);
Serial.print('0');
}
}
}
}
================================================
FILE: examples/SendAllProtocols/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/SendAllProtocols/SendAllProtocols.ino
================================================
/*
* SendAllProtocols.cpp
*
* Sends 39 protocols for testing purposes
*
* To disable one of them or to enable other protocols, specify this before the "#include " line.
* If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example).
* The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example).
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set library modifiers first to set output pin etc.
*/
#include "PinDefinitionsAndMore.h"
#define IRSND_IR_FREQUENCY 38000
#if ! (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__))
#define IRSND_PROTOCOL_NAMES 1
#endif
//#define IRSND_GENERATE_NO_SEND_RF // for back to back tests
#include
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irsnd_data;
void setup()
{
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
Serial.println(); // to separate it from the internal boot output
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
Serial.print(F("Send sample frequency="));
Serial.print(F_INTERRUPTS);
Serial.println(F(" Hz"));
irsnd_init();
irmp_irsnd_LEDFeedback(true); // Enable send signal feedback at LED_BUILTIN
Serial.println(F("Send IR signals at pin " STR(IRSND_OUTPUT_PIN)));
delay(1000);
}
void loop()
{
static uint16_t sAddress = 0x201;
static uint16_t sCommand = 0x201;
static uint8_t sRepeats = 0;
Serial.print(F("Now sending all with "));
Serial.print(sRepeats);
Serial.println(F(" repeats"));
for (uint_fast8_t i = 0; i < sizeof(irsnd_used_protocol_index); ++i)
{
irsnd_data.protocol = pgm_read_byte(&irsnd_used_protocol_index[i]);
irsnd_data.address = sAddress;
irsnd_data.command = sCommand;
irsnd_data.flags = sRepeats;
// true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending.
if (!irsnd_send_data(&irsnd_data, true))
{
Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print()
}
irsnd_data_print(&Serial, &irsnd_data);
sAddress += 0x101;
sCommand += 0x101;
delay(1000);
}
Serial.println();
Serial.println();
sRepeats++;
// we have 0x27 protocols now start with next number range
sAddress = (sAddress & 0xC0) + 0x40;
sCommand = sAddress;
delay(2000);
}
================================================
FILE: examples/SendAllProtocols/SendAllProtocols.log
================================================
START ../src/SendAllProtocols.cpp from Mar 17 2026
Using library version 3.7.0
Send sample frequency=19000 Hz
Send IR signals at pin 3
Protocol=SIRCS Address=0x1 Command=0x1
Protocol=NEC Address=0x2 Command=0x2
Protocol=SAMSUNG Address=0x3 Command=0x3
Protocol=MATSUSH Address=0x4 Command=0x4
Protocol=KASEIKYO Address=0x5 Command=0x5
Protocol=RECS80 Address=0x6 Command=0x6
Protocol=RC5 Address=0x7 Command=0x7
Protocol=DENON Address=0x8 Command=0x8
Protocol=RC6 Address=0x9 Command=0x9
Protocol=SAMSG32 Address=0xA Command=0xA
Protocol=APPLE Address=0xB Command=0xB
Protocol=RECS80EX Address=0xC Command=0xC
Protocol=NUBERT Address=0xD Command=0xD
Protocol=GRUNDIG Address=0xE Command=0xE
Protocol=NOKIA Address=0xF Command=0xF
Protocol=SIEMENS Address=0x10 Command=0x10
Protocol=FDC Address=0x11 Command=0x11
Protocol=RCCAR Address=0x12 Command=0x12
Protocol=JVC Address=0x13 Command=0x13
Protocol=RC6A Address=0x14 Command=0x14
Protocol=NIKON Address=0x15 Command=0x15
Protocol=RUWIDO Address=0x16 Command=0x16
Protocol=NEC16 Address=0x17 Command=0x17
Protocol=NEC42 Address=0x18 Command=0x18
Protocol=LEGO Address=0x19 Command=0x19
Protocol=THOMSON Address=0x1A Command=0x1A
Protocol=BOSE Address=0x1B Command=0x1B
Protocol=A1TVBOX Address=0x1C Command=0x1C
Protocol=TELEFUNKEN Address=0x1D Command=0x1D
Protocol=ROOMBA Address=0x1E Command=0x1E
Protocol=SPEAKER Address=0x1F Command=0x1F
Protocol=LGAIR Address=0x20 Command=0x20
Protocol=SAMSG48 Address=0x21 Command=0x21
Protocol=PENTAX Address=0x22 Command=0x22
Protocol=FAN Address=0x23 Command=0x23
Protocol=ACP24 Address=0x24 Command=0x24
Protocol=TECHNICS Address=0x25 Command=0x25
Protocol=PANASONIC Address=0x26 Command=0x26
Protocol=MITSU_HEAVY Address=0x27 Command=0x27
Now sending all with number of repeats=1
Protocol=SIRCS Address=0x40 Command=0x40 Repeats=1
Protocol=NEC Address=0x41 Command=0x41 Repeats=1
Protocol=SAMSUNG Address=0x42 Command=0x42 Repeats=1
Protocol=MATSUSH Address=0x43 Command=0x43 Repeats=1
================================================
FILE: examples/SimpleReceiver/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/SimpleReceiver/SimpleReceiver.ino
================================================
/*
* SimpleReceiver.cpp
*
* Receives IR protocol data of 15 main protocols.
*
* *****************************************************************************************************************************
* To access the library files from your sketch, you have to first use `Sketch > Show Sketch Folder (Ctrl+K)` in the Arduino IDE.
* Then navigate to the parallel `libraries` folder and select the library you want to access.
* The library files itself are located in the `src` sub-directory.
* If you did not yet store the example as your own sketch, then with Ctrl+K you are instantly in the right library folder.
* *****************************************************************************************************************************
*
*
* The following IR protocols are enabled by default:
* Sony SIRCS
* NEC + APPLE
* Samsung + Samsg32
* Kaseikyo
*
* Plus 11 other main protocols by including irmpMain15.h instead of irmp.h
* JVC, NEC16, NEC42, Matsushita, DENON, Sharp, RC5, RC6 & RC6A, IR60 (SDA2008) Grundig, Siemens Gigaset, Nokia
*
* To disable one of them or to enable other protocols, specify this before the "#include " line.
* If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example).
* The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example).
*
* Copyright (C) 2019 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
/*
* Set input pin and output pin definitions etc.
*/
#include "PinDefinitionsAndMore.h"
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. Must before #include
//#include // This enables 15 main protocols
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol
//#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // this enables only one protocol
/*
* We use LED_BUILTIN as feedback for commands 0x40 and 0x48 and cannot use it as feedback LED for receiving
*/
#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
#endif
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irmp_data;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
// Wait until Serial Monitor is attached.
// Required for boards using USB code for Serial like Leonardo.
// Is void for USB Serial implementations using external chips e.g. a CH340.
while (!Serial)
;
// !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irmp_init();
Serial.print(F("Ready to receive IR signals of protocols: "));
irmp_print_active_protocols(&Serial);
Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
/*
* We use LED_BUILTIN as feedback for commands 0x40 and 0x48 and cannot use it as feedback LED for receiving
*/
#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN
Serial.println(F("IR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN)));
#endif
}
void loop() {
/*
* Check if new data available and get them
*/
if (irmp_get_data(&irmp_data)) {
/*
* Skip repetitions of command
*/
if (!(irmp_data.flags & IRMP_FLAG_REPETITION)) {
/*
* Here data is available and is no repetition -> evaluate IR command
*/
switch (irmp_data.command) {
case 0x48: // 72
case 0x40: // 64
digitalWrite(LED_BUILTIN, LOW);
delay(4000);
break;
default:
digitalWrite(LED_BUILTIN, HIGH);
break;
}
}
irmp_result_print(&irmp_data);
}
}
================================================
FILE: examples/SimpleSender/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRMP examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4
* ATtinyX5 0|PB0 4|PB4 3|PB3
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark pro
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 %
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN 14 // D5
#define IRSND_OUTPUT_PIN 12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN 6
#define IRSND_OUTPUT_PIN 7
#define TONE_PIN 10
#elif defined(ESP32)
#define IRMP_INPUT_PIN 15 // D15
#define IRSND_OUTPUT_PIN 4 // D4
#include
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN PA6
#define IRSND_OUTPUT_PIN PA7
#define TONE_PIN PA3
#define IR_TIMING_TEST_PIN PA5
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN 0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN 3
//#define IR_TIMING_TEST_PIN 3
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4
# else
#define IRMP_INPUT_PIN 3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN 7
# endif
#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN 3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN 9
#define IR_TIMING_TEST_PIN 8
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN 11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN 4 // GPIO16
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN 16
#define TONE_PIN 17
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2
#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN 2
#define IRSND_OUTPUT_PIN 3
#define TONE_PIN 4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
================================================
FILE: examples/SimpleSender/SimpleSender.ino
================================================
/*
* SimpleSender.cpp
*
* Sends NEC or Samsung protocol frames.
* Is able to send IR protocol data of 15 main protocols.
*
* Sony SIRCS
* NEC + APPLE
* Samsung + Samsg32
* Kaseikyo
*
* Plus 11 other main protocols
* JVC, NEC16, NEC42, Matsushita, DENON, Sharp, RC5, RC6 & RC6A, IR60 (SDA2008) Grundig, Siemens Gigaset, Nokia
*
* To disable one of them or to enable other protocols, specify this before the "#include " line.
* If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example).
* The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example).
*
* Copyright (C) 2019-2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#include
//#define SEND_SAMSUNG // else send NEC
/*
* Set library modifiers first to set output pin etc.
*/
#include "PinDefinitionsAndMore.h"
//#define IR_OUTPUT_IS_ACTIVE_LOW
#define IRSND_IR_FREQUENCY 38000
#define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH.
#include
// or disable #include and use only one protocol to save programming space
//#define IRSND_SUPPORT_NEC_PROTOCOL 1
//#define IRSND_SUPPORT_NEC_PROTOCOL 1
/*
* After setting the definitions we can include the code and compile it.
*/
#include
IRMP_DATA irsnd_data;
#if defined(SEND_SAMSUNG)
union WordUnion
{
struct
{
uint8_t LowByte;
uint8_t HighByte;
} UByte;
struct
{
int8_t LowByte;
int8_t HighByte;
} Byte;
uint8_t UBytes[2];
int8_t Bytes[2];
uint16_t UWord;
int16_t Word;
uint8_t *BytePointer;
};
#endif
void setup() {
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));
irsnd_init();
irmp_irsnd_LEDFeedback(true); // Enable send signal feedback at LED_BUILTIN
Serial.println(F("Send IR signals at pin " STR(IRSND_OUTPUT_PIN)));
#if defined(SEND_SAMSUNG)
/*
* Send Samsung32
*/
irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL;
irsnd_data.address = 0x0707;
irsnd_data.command = 0xFB04; // For my Samsung, the high byte is the inverse of the low byte
irsnd_data.flags = 0; // repeat frame 0 time
#else
/*
* Send NEC
*/
irsnd_data.protocol = IRMP_NEC_PROTOCOL;
irsnd_data.address = 0x0707;
irsnd_data.command = 0xFB; // The required inverse of the 8 bit command is added by the send routine.
irsnd_data.flags = 2; // repeat frame 2 times
#endif
// true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending.
if (!irsnd_send_data(&irsnd_data, true)) {
Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print()
}
irsnd_data_print(&Serial, &irsnd_data);
}
void loop() {
delay(5000);
irsnd_data.command++;
#if defined(SEND_SAMSUNG)
// For my Samsung remote, the high byte is the inverse of the low byte
WordUnion tNextCommand; // using WordUnion saves 14 bytes program memory for the next 3 lines
tNextCommand.UWord = irsnd_data.command;
tNextCommand.UByte.HighByte = ~tNextCommand.UByte.LowByte;
irsnd_data.command = tNextCommand.UWord;
#endif
irsnd_send_data(&irsnd_data, true);
irsnd_data_print(&Serial, &irsnd_data);
}
================================================
FILE: examples/TinyReceiver/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2021-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 Arduino
* ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* MKR* 1 3 4
* SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 2 3 4
* ESP32-S3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN PIN_PB3
#define _IR_TIMING_TEST_PIN PIN_PB3
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
# elif !defined(PIN_PA3)
#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
# endif
# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
#define IR_SEND_PIN PIN_PD4 // 4
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock
#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA7 // 3
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB1 // 6
# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 13
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc.
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit
// We have no built in LED at pin 13 -> reuse RX LED
#undef LED_BUILTIN
#define LED_BUILTIN LED_BUILTIN_RX
# endif
# endif // defined(__AVR_ATtiny25__)...
#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4
// To be compatible with Uno R3.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it#
#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
// ESP32 - C3 super mini
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
// ESP32 - C3 other
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 9
#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV)
// ESP32 - S3 - !!! NOT tested !!!
#define IR_RECEIVE_PIN 15 // alternatively 13
#define IR_SEND_PIN 16 // alternatively 14
#define TONE_PIN 17
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
#define IR_SEND_PIN PA7
#define IR_SEND_PIN_STRING "PA7"
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
#define APPLICATION_PIN_STRING "PA2"
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards
#define IR_RECEIVE_PIN 11
#define IR_SEND_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED
// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect
#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IR_SEND_PIN 4 // GPIO16
#define TONE_PIN 5
#define APPLICATION_PIN 6
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 8
#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16 // GPIO16
#define TONE_PIN 17
#define APPLICATION_PIN 18
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 20
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
#define LED_BUILTIN D7
/*
* 4 times the same (default) layout for easy adaption in the future
*/
#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
# else
#define IR_RECEIVE_PIN 2
# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0)
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
#endif
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#elif defined (NRF51) // BBC micro:bit
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define APPLICATION_PIN 1
#define _IR_TIMING_TEST_PIN 4
#define tone(...) void() // no tone() available
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#else
#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
#if !defined (RAMEND)
#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined
#endif
================================================
FILE: examples/TinyReceiver/TinyReceiver.ino
================================================
/*
* TinyReceiver.cpp
*
* Small memory footprint and no timer usage!
*
* Receives IR protocol data of NEC protocol using pin change interrupts.
* For each complete IR frame/command received, the decoded data is copied to the TinyIRReceiverData structure
* and the handleReceivedTinyIRData() function is called in an interrupt context.
* However, interrupts are explicitly enabled here to allow the use of delay() and millis() etc.
* !!!!!!!!!!!!!!!!!!!!!!
* Functions called in interrupt context should be running as short as possible,
* !!!!!!!!!!!!!!!!!!!!!
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command.
* This results in a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
* This file is also part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2026 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#include
#include "PinDefinitionsAndMore.h" // Set IR_RECEIVE_PIN for different CPU's
//#define DEBUG // to see if attachInterrupt is used
//#define TRACE // to see the state of the ISR state machine
/*
* Protocol selection
*/
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
/*
* Set compile options to modify the generated code.
*/
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // include the code
void setup() {
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
// Wait until Serial Monitor is attached.
// Required for boards using USB code for Serial like Leonardo.
// Is void for USB Serial implementations using external chips e.g. a CH340.
while (!Serial)
;
// !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
#if defined(ESP8266) || defined(ESP32)
Serial.println();
#endif
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
// Enables the interrupt generation on change of IR input signal
if (!initPCIInterruptForTinyReceiver()) {
Serial.println(F("No interrupt available for pin " STR(IR_RECEIVE_PIN))); // optimized out by the compiler, if not required :-)
}
#if defined(USE_FAST_PROTOCOL)
Serial.println(F("Ready to receive Fast IR signals at pin " STR(IR_RECEIVE_PIN)));
#else
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN)));
#endif
}
void loop() {
if (TinyReceiverDecode()) {
/*
* The library has already copied the data used for this output,
* so there is no need to do this in the callback function.
*/
#if !defined(USE_FAST_PROTOCOL)
// We have no address at FAST protocol
Serial.print(F("Address=0x"));
Serial.print(TinyIRReceiverData.Address, HEX);
Serial.print(' ');
#endif
Serial.print(F("Command=0x"));
Serial.print(TinyIRReceiverData.Command, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F(" Repeat"));
}
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
Serial.print(F(" Parity failed"));
#if !defined(USE_EXTENDED_NEC_PROTOCOL) && !defined(USE_ONKYO_PROTOCOL)
Serial.print(F(", try USE_EXTENDED_NEC_PROTOCOL or USE_ONKYO_PROTOCOL"));
#endif
}
Serial.println();
}
/*
* Put your code here
*/
/*
* No resume() required :-)
*/
}
/*
* Optional code, if you require a callback
*/
#if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
/*
* This is the function, which is called if a complete frame was received
* This function is executed in an ISR (Interrupt Service Routine) context but with interrupts enabled!
* However, it is always best to keep this callback function short and fast!
*/
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
# endif
void handleReceivedTinyIRData() {
# if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
/*
* Printing is not allowed in ISR context for RTOS based cores like ESP, even when interrupts are enabled.
* For Mbed we get a kernel panic and "Error Message: Semaphore: 0x0, Not allowed in ISR context" for Serial.print()
* for ESP32 we get a "Guru Meditation Error: Core 1 panic'ed" (we also have an RTOS running!)
*/
# else
// As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
printTinyReceiverResultMinimal(&Serial);
# endif
if (TinyIRReceiverData.Command == 0x10) {
// do something SHORT here
} else if (TinyIRReceiverData.Command == 0x11) {
// do something SHORT here too
}
}
#endif
================================================
FILE: examples/TinySender/PinDefinitionsAndMore.h
================================================
/*
* PinDefinitionsAndMore.h
*
* Contains pin definitions for IRremote examples for various platforms
* as well as definitions for feedback LED and tone() and includes
*
* Copyright (C) 2021-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 Arduino
* ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore
* ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
* ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* MKR* 1 3 4
* SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 2 3 4
* ESP32-S3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN PIN_PB3
#define _IR_TIMING_TEST_PIN PIN_PB3
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
# elif !defined(PIN_PA3)
#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
# endif
# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
#define IR_SEND_PIN PIN_PD4 // 4
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock
#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA7 // 3
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB2 // 5
# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5
#define TONE_PIN PIN_PA3 // 1 TCA0-WO3
#define APPLICATION_PIN PIN_PB1 // 6
# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 13
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc.
#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit
// We have no built in LED at pin 13 -> reuse RX LED
#undef LED_BUILTIN
#define LED_BUILTIN LED_BUILTIN_RX
# endif
# endif // defined(__AVR_ATtiny25__)...
#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4
// To be compatible with Uno R3.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW
#define IR_RECEIVE_PIN 14 // D5
#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED
#define _IR_TIMING_TEST_PIN 2 // D4
#define APPLICATION_PIN 13 // D7
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it#
#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
// ESP32 - C3 super mini
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
// ESP32 - C3 other
#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 9
#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV)
// ESP32 - S3 - !!! NOT tested !!!
#define IR_RECEIVE_PIN 15 // alternatively 13
#define IR_SEND_PIN 16 // alternatively 14
#define TONE_PIN 17
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
# if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
# endif
# if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
#define IR_SEND_PIN PA7
#define IR_SEND_PIN_STRING "PA7"
#define TONE_PIN PA3
#define _IR_TIMING_TEST_PIN PA5
#define APPLICATION_PIN PA2
#define APPLICATION_PIN_STRING "PA2"
# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
// BluePill LED is active low
#define FEEDBACK_LED_IS_ACTIVE_LOW
# endif
#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards
#define IR_RECEIVE_PIN 11
#define IR_SEND_PIN 12
#define TONE_PIN 5
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED
// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect
#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IR_SEND_PIN 4 // GPIO16
#define TONE_PIN 5
#define APPLICATION_PIN 6
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 8
#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IR_SEND_PIN 16 // GPIO16
#define TONE_PIN 17
#define APPLICATION_PIN 18
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 20
// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN 6
#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
#define LED_BUILTIN D7
/*
* 4 times the same (default) layout for easy adaption in the future
*/
#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc.
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
# else
#define IR_RECEIVE_PIN 2
# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0)
// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB
#endif
// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
#elif defined (NRF51) // BBC micro:bit
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define APPLICATION_PIN 1
#define _IR_TIMING_TEST_PIN 4
#define tone(...) void() // no tone() available
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#else
#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp
# endif
#endif
#if !defined (FLASHEND)
#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined
#endif
#if !defined (RAMEND)
#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined
#endif
================================================
FILE: examples/TinySender/TinySender.ino
================================================
/*
* TinySender.cpp
*
* Example for sending using TinyIR. By default sends simultaneously using all supported protocols
* To use a single protocol, simply delete or comment out all unneeded protocols in the main loop
* Program size is significantly reduced when using a single protocol
* For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender,
* which does the same, but uses the IRRemote library (and is therefore much more flexible).
*
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
* This file is also part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#include
#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's
#include "TinyIRSender.hpp"
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
Serial.print(F("Send IR signals at pin "));
Serial.println(IR_SEND_PIN);
}
/*
* Set up the data to be sent.
* The compiler is intelligent and removes the code for 16 bit address handling if we call it with an uint8_t address :-).
* Using an uint16_t address or data requires additional 28 bytes program memory for NEC and 56 bytes program memory for FAST.
*/
uint8_t sAddress = 0x02;
//uint16_t sAddress = 0x02;
uint8_t sCommand = 0x34;
//uint16_t sCommand = 0x34;
uint8_t sRepeats = 0;
void loop() {
/*
* Print current send values
*/
Serial.println();
Serial.print(F("Send now:"));
Serial.print(F(" address=0x"));
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.print(sRepeats);
Serial.println();
// Send with FAST
// No address and only 16 bits of data, interpreted as 8 bit command and 8 bit inverted command for parity checking
Serial.println(F("Send FAST with 8 bit command"));
Serial.flush();
sendFAST(IR_SEND_PIN, sCommand, sRepeats);
// Send with NEC
// NEC uses 8 bit address and 8 bit command each with 8 bit inverted parity checks
// However, sendNEC will accept 16 bit address and commands too (but remove the parity checks)
Serial.println(F("Send NEC with 8 bit address and command"));
Serial.flush();
sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats);
// Send with Extended NEC
// Like NEC, but the address is forced 16 bits with no parity check
Serial.println(F("Send ExtendedNEC with 16 bit address and 8 bit command"));
Serial.flush();
sendExtendedNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats);
// Send with ONKYO
// Like NEC, but both the address and command are forced 16 bits with no parity check
Serial.println(F("Send ONKYO with 16 bit address and command"));
Serial.flush();
sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats);
// Send with NEC2
// Instead of sending the NEC special repeat code, sends the full original frame for repeats
// Sending NEC2 is done by setting the optional bool NEC2Repeats argument to true (defaults to false)
// sendExtendedNEC and sendONKYO also support the NEC2Repeats argument for full frame repeats (not demonstrated here)
Serial.println(F("Send NEC2 with 8 bit address and command and original frame repeats"));
Serial.flush();
sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true);
/*
* Increment send values
* Also increment address just for demonstration, which normally makes no sense
*/
sAddress += 0x0101;
sCommand += 0x11;
sRepeats++;
// clip repeats at 4
if (sRepeats > 4) {
sRepeats = 4;
}
delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
}
================================================
FILE: keywords.txt
================================================
#######################################
# Syntax Coloring Map For IRMP
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
irmp_protocol_names KEYWORD1
IRMP_DATA KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
irmp_init KEYWORD2
irmp_register_complete_callback_function KEYWORD2
irmp_IsBusy KEYWORD2
irmp_print_active_protocols KEYWORD2
irmp_get_data KEYWORD2
irmp_result_print KEYWORD2
irsnd_init KEYWORD2
irsnd_send_data KEYWORD2
irsnd_data_print KEYWORD2
irsnd_is_busy KEYWORD2
irmp_irsnd_LEDFeedback KEYWORD2
disableIRTimerInterrupt KEYWORD2
enableIRTimerInterrupt KEYWORD2
storeIRTimer KEYWORD2
restoreIRTimer KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
IRMP_FLAG_REPETITION LITERAL1
IRMP_FLAG_RELEASE LITERAL1
IRMP_PROTOCOL_NAMES LITERAL1
IRMP_USE_COMPLETE_CALLBACK LITERAL1
F_INTERRUPTS LITERAL1
IRSND_IR_FREQUENCY LITERAL1
IR_OUTPUT_IS_ACTIVE_LOW LITERAL1
IRMP_ENABLE_PIN_CHANGE_INTERRUPT LITERAL1
USE_ONE_TIMER_FOR_IRMP_AND_IRSND LITERAL1
IRMP_ENABLE_RELEASE_DETECTION LITERAL1
IRMP_HIGH_ACTIVE LITERAL1
================================================
FILE: library.json
================================================
{
"name": "IRMP",
"version": "3.7.0",
"keywords": "infrared, ir, remote",
"description": "Receive and Send infrared signals from your remote.",
"homepage": "https://github.com/IRMP-org/IRMP",
"repository": {
"type": "git",
"url": "https://github.com/IRMP-org/IRMP.git"
},
"authors": [
{
"name": "Armin Joachimsmeyer",
"email": "armin.arduino@gmail.com",
"maintainer": true
},
{
"name": "Frank Meyer",
"email": "frank@fli4l.de"
}
],
"license": "GPL-3.0-or-later",
"frameworks": "arduino",
"platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
"headers": ["irmp.hpp", "irsnd.hpp"],
"examples": "examples/*/*.ino",
"export": {"exclude": [".github", "pictures"]}
}
================================================
FILE: library.properties
================================================
name=IRMP
version=3.7.0
author=Frank Meyer, Armin Joachimsmeyer
maintainer=Armin Joachimsmeyer , frank@fli4l.de
sentence=Receive and send infrared signals.
paragraph=Supports 50 different IR and 3 RF protocols. Can receive 40 protocols concurrently. Supports ATtiny, AVR and MegaAVR boards as well as ESP8266, ESP32, STM32, SAMD, RP2040 and Apollo boards.
category=Signal Input/Output
url=https://github.com/IRMP-org/IRMP
architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,apollo3,mbed,mbed_nano,rp2040
includes=irmp.hpp
================================================
FILE: src/IRCommandDispatcher.h
================================================
/*
* IRCommandDispatcher.h
*
* Library to process IR commands by calling functions specified in a mapping array.
*
* To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* Copyright (C) 2019-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRCommandDispatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef _IR_COMMAND_DISPATCHER_H
#define _IR_COMMAND_DISPATCHER_H
#include
//#define DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT // Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry.
//#define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries.
#if defined(USE_DISPATCHER_COMMAND_STRINGS)
#define COMMAND_STRING(anyString) anyString
#else
#define COMMAND_STRING(anyString)
#endif
/*
* For command mapping file
*/
#define IR_COMMAND_FLAG_BLOCKING 0x00 // default - blocking command, repeat not accepted, only one command at a time. Stops an already running command.
#define IR_COMMAND_FLAG_REPEATABLE 0x01 // repeat accepted
#define IR_COMMAND_FLAG_NON_BLOCKING 0x02 // Non blocking (short) command that can be processed any time and may interrupt other IR commands - used for stop, set direction etc.
#define IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING (IR_COMMAND_FLAG_REPEATABLE | IR_COMMAND_FLAG_NON_BLOCKING)
#define IR_COMMAND_FLAG_BEEP 0x04 // Do a single short beep before executing command. May not be useful for short or repeating commands.
#define IR_COMMAND_FLAG_BLOCKING_BEEP (IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP)
#if !defined(IS_STOP_REQUESTED)
#define IS_STOP_REQUESTED IRDispatcher.requestToStopReceived
#endif
#if !defined(RETURN_IF_STOP)
#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return
#endif
#if !defined(BREAK_IF_STOP)
#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break
#endif
#if !defined(DELAY_AND_RETURN_IF_STOP)
#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return
#endif
/*
* Define as COMMAND_EMPTY a code which is not sent by the remote - otherwise please redefine it here
*/
#if defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT)
#define COMMAND_EMPTY __UINT_FAST16_MAX__ // 0xFFFF code no command
typedef uint_fast16_t IRCommandType;
#else
typedef uint_fast8_t IRCommandType;
#define COMMAND_EMPTY __UINT_FAST8_MAX__ // 0xFF code no command
#endif
// Basic mapping structure
struct IRToCommandMappingStruct {
IRCommandType IRCode;
uint8_t Flags;
void (*CommandToCall)();
#if defined(USE_DISPATCHER_COMMAND_STRINGS)
const char *CommandString;
#endif
};
struct IRDataForCommandDispatcherStruct {
uint16_t address; // to distinguish between multiple senders
IRCommandType command;
bool isRepeat;
volatile uint32_t MillisOfLastCode; // millis() of last IR command -including repeats!- received - for timeouts etc.
volatile bool isAvailable; // flag for a polling interpreting function, that a new command has arrived. Is set true by library and set false by main loop.
};
class IRCommandDispatcher {
public:
void init();
void printIRInfo(Print *aSerial);
bool checkAndRunNonBlockingCommands();
bool checkAndRunSuspendedBlockingCommands();
void setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext);
bool delayAndCheckForStop(uint16_t aDelayMillis);
// The main dispatcher function
void checkAndCallCommand(bool aCallBlockingCommandImmediately);
void printIRCommandString(Print *aSerial, IRCommandType aCommand);
void printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex);
void setRequestToStopReceived(bool aRequestToStopReceived = true);
IRCommandType currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command
IRCommandType lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop
IRCommandType BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop
bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command
/*
* Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP).
* It is set if a blocking IR command received, which cannot be executed directly. Can be reset by main loop, if command has stopped.
* It is reset before executing a blocking command.
*/
volatile bool requestToStopReceived;
/*
* This flag must be true, if we have a function, which want to interpret the IR codes by itself e.g. the calibrate function of QuadrupedControl
*/
bool doNotUseDispatcher = false;
struct IRDataForCommandDispatcherStruct IRReceivedData;
};
extern IRCommandDispatcher IRDispatcher;
#endif // _IR_COMMAND_DISPATCHER_H
================================================
FILE: src/IRCommandDispatcher.hpp
================================================
/*
* IRCommandDispatcher.hpp
*
* Library to process IR commands by calling functions specified in a mapping array.
* Commands can be tagged as blocking or non blocking.
*
* To run this example you need to install the "IRremote" or "IRMP" library.
* Install it under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* The IR library calls a callback function, which executes a non blocking command directly in ISR (Interrupt Service Routine) context!
* A blocking command is stored and sets a stop flag for an already running blocking function to terminate.
* The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands().
*
* Copyright (C) 2019-2026 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* IRCommandDispatcher is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* Program behavior is modified by the following macros
* USE_TINY_IR_RECEIVER
* USE_IRMP_LIBRARY
* DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT
*/
#ifndef _IR_COMMAND_DISPATCHER_HPP
#define _IR_COMMAND_DISPATCHER_HPP
#include
#include "IRCommandDispatcher.h"
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
//#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
//#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding
//#define USE_IRMP_LIBRARY // The IRMP library is used for decoding
#if !defined(USE_TINY_IR_RECEIVER) && !defined(USE_IRREMOTE_LIBRARY) && !defined(USE_IRMP_LIBRARY)
#define USE_TINY_IR_RECEIVER // Set TiniIR as default library
#endif
IRCommandDispatcher IRDispatcher;
#if defined(USE_TINY_IR_RECEIVER)
/******************************
* Code for the TinyIR library
******************************/
#if defined(USE_ONKYO_PROTOCOL) && ! defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT)
#warning ONKYO protocol has 16 bit commands so activating of DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT is recommended
#endif
#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the function "handleReceivedTinyIRData()" below each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // included in "IRremote" and "IRMP" library
// This block must be located after the includes of other *.hpp files
//#define LOCAL_INFO // This enables info output only for this file
//#define LOCAL_DEBUG // This enables debug output only for this file - only for development
//#define LOCAL_TRACE // This enables trace output only for this file - only for development
#include "LocalDebugLevelStart.h"
void IRCommandDispatcher::init() {
initPCIInterruptForTinyIRReceiver();
}
/*
* This is the TinyIRReceiver callback function, which is called if a complete command was received.
* Interrupts are enabled here to allow e.g. delay() in commands.
* Copy the (volatile) IR data in order not to be overwritten on receiving of next frame.
* Next, check for right address if IR_ADDRESS is defined.
* At last call the dispatcher.
*/
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
# endif
void handleReceivedTinyIRData() {
IRDispatcher.IRReceivedData.address = TinyIRReceiverData.Address;
IRDispatcher.IRReceivedData.command = TinyIRReceiverData.Command;
IRDispatcher.IRReceivedData.isRepeat = TinyIRReceiverData.Flags & IRDATA_FLAGS_IS_REPEAT;
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
# if defined(LOCAL_INFO)
printTinyIRReceiverResultMinimal(&Serial);
# endif
# if defined(IR_ADDRESS)
// if available, compare address. TinyIRReceiverData.Address saves 6 bytes
if (TinyIRReceiverData.Address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
INFO_PRINT(F("Wrong address. Expected 0x"));
INFO_PRINTLN(IR_ADDRESS, HEX);
} else
# endif
{
IRDispatcher.IRReceivedData.isAvailable = true;
// check if dispatcher enabled
if (!IRDispatcher.doNotUseDispatcher) {
/*
* Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context,
* others are stored for main loop which calls checkAndRunSuspendedBlockingCommands()
*/
IRDispatcher.checkAndCallCommand(false);
}
}
}
#elif defined(USE_IRREMOTE_LIBRARY)
/*********************************
* Code for the IRremote library
*********************************/
#define DECODE_NEC // Includes Apple and Onkyo
#include "IRremote.hpp"
// This block must be located after the includes of other *.hpp files
//#define LOCAL_INFO // This enables info output only for this file
//#define LOCAL_DEBUG // This enables debug output only for this file - only for development
//#define LOCAL_TRACE // This enables trace output only for this file - only for development
#include "LocalDebugLevelStart.h"
void ReceiveCompleteCallbackHandler();
void IRCommandDispatcher::init() {
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
/*
* Tell the ISR to call this function, when a complete frame has been received
*/
IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler);
}
/*
* Callback function
* Here we know, that data is available.
* This function is executed in an ISR (Interrupt Service Routine) context.
* This means that interrupts are blocked here, so delay(), millis() and Serial prints of data longer than the print buffer size etc. will block forever.
* This is because they require their internal interrupt routines to run in order to return.
* Therefore it is best to make this callback function short and fast!
* A dirty hack is to enable interrupts again by calling sei() (enable interrupt again), but you should know what you are doing,
*/
#if defined(ESP32) || defined(ESP8266)
IRAM_ATTR
# endif
void ReceiveCompleteCallbackHandler() {
/*
* Fill IrReceiver.decodedIRData
*/
IrReceiver.decode();
IRDispatcher.IRReceivedData.address = IrReceiver.decodedIRData.address;
IRDispatcher.IRReceivedData.command = IrReceiver.decodedIRData.command;
IRDispatcher.IRReceivedData.isRepeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT;
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
// Interrupts are already enabled for SUPPORT_MULTIPLE_RECEIVER_INSTANCES
#if !defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) && !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled
interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration.
# endif
# if defined(LOCAL_INFO)
IrReceiver.printIRResultMinimal(&Serial);
Serial.println();
# endif
/*
* Enable receiving of the next frame.
*/
IrReceiver.resume();
# if defined(IR_ADDRESS)
// if available, compare address
if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
INFO_PRINT(F("Wrong address. Expected 0x"));
INFO_PRINTLN(IR_ADDRESS, HEX);
} else
# endif
{
IRDispatcher.IRReceivedData.isAvailable = true;
// check if dispatcher enabled
if (!IRDispatcher.doNotUseDispatcher) {
/*
* Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context,
* others are stored for main loop which calls checkAndRunSuspendedBlockingCommands()
*/
IRDispatcher.checkAndCallCommand(false);
}
}
}
#elif defined(USE_IRMP_LIBRARY)
/******************************
* Code for the IRMP library
******************************/
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used.
#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings for printIRInfo()
#include "irmp.hpp"
#include "LocalDebugLevelStart.h"
IRMP_DATA irmp_data;
void handleReceivedIRData();
void IRCommandDispatcher::init()
{
irmp_init();
irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp
}
/*
* This is the callback function, which is called if a complete command was received.
* Interrupts are NOT enabled here so we must do it manually to allow e.g. delay() in commands.
* Copy the (volatile) IR data in order not to be overwritten on receiving of next frame.
* Next, check for right address if IR_ADDRESS is defined.
* At last call the dispatcher.
*/
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void handleReceivedIRData()
{
irmp_get_data(&irmp_data);
IRDispatcher.IRReceivedData.address = irmp_data.address;
IRDispatcher.IRReceivedData.command = irmp_data.command;
IRDispatcher.IRReceivedData.isRepeat = irmp_data.flags & IRMP_FLAG_REPETITION;
IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled
interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration.
# endif
# if defined(LOCAL_INFO)
irmp_result_print(&Serial, &irmp_data);
# endif
# if defined(IR_ADDRESS)
// if available, compare address
if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) {
INFO_PRINT(F("Wrong address. Expected 0x"));
INFO_PRINTLN(IR_ADDRESS, HEX);
} else
# endif
{
IRDispatcher.IRReceivedData.isAvailable = true;
// check if dispatcher enabled
if (!IRDispatcher.doNotUseDispatcher)
{
/*
* Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context,
* others are stored for main loop which calls checkAndRunSuspendedBlockingCommands()
*/
IRDispatcher.checkAndCallCommand(false);
}
}
}
#endif // elif defined(USE_IRMP_LIBRARY)
/*******************************************
* Start of the IR library independent code
*******************************************/
void IRCommandDispatcher::printIRInfo(Print *aSerial) {
aSerial->println();
// For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h
#if defined(USE_IRMP_LIBRARY)
# if defined(IR_REMOTE_NAME)
aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IRMP_INPUT_PIN)));
# else
aSerial->println(F("Listening to IR remote at pin " STR(IRMP_INPUT_PIN)));
# endif
aSerial->print(F("Accepted protocols are: "));
irmp_print_active_protocols(&Serial);
aSerial->println();
#else
# if defined(IR_REMOTE_NAME)
aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IR_RECEIVE_PIN)));
# else
aSerial->println(F("Listening to IR remote at pin " STR(IR_RECEIVE_PIN)));
# endif
#endif
}
/*
* The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands()
* Non blocking commands are executed immediately, blocking commands are executed if no other command is just running.
* If another blocking command is currently running, the request to stop is set
* and the command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands().
* This function sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived
* @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running.
* Should be false if called by ISR in order not to block ISR. Is true when called from checkAndRunSuspendedBlockingCommands().
*/
void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) {
if (IRReceivedData.command == COMMAND_EMPTY) {
return;
}
/*
* Search for command in Array of IRToCommandMappingStruct
*/
for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
if (IRReceivedData.command == IRMapping[i].IRCode) {
/*
* Command found
*/
#if defined(LOCAL_INFO)
# if defined(__AVR__)
# if defined(USE_DISPATCHER_COMMAND_STRINGS)
const __FlashStringHelper *tCommandName = reinterpret_cast(IRMapping[i].CommandString);
# else
char tCommandName[7];
snprintf_P(tCommandName, sizeof(tCommandName), PSTR("0x%x"), IRMapping[i].IRCode);
# endif
# else
# if defined(USE_DISPATCHER_COMMAND_STRINGS)
const char *tCommandName = IRMapping[i].CommandString;
# else
char tCommandName[7];
snprintf(tCommandName, sizeof(tCommandName), "0x%x", IRMapping[i].IRCode);
# endif
# endif
#endif
/*
* Check for repeat and if repeat is allowed for the current command
*/
if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) {
DEBUG_PRINT(F("Repeats of command \""));
DEBUG_PRINT(tCommandName);
DEBUG_PRINTLN("\" not accepted");
return;
}
/*
* Do not accept recursive call of the same command
*/
if (currentBlockingCommandCalled == IRReceivedData.command) {
DEBUG_PRINT(F("Recursive command \""));
DEBUG_PRINT(tCommandName);
DEBUG_PRINTLN("\" not accepted");
return;
}
/*
* Execute commands
*/
bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING);
if (tIsNonBlockingCommand) {
// short command here, just call
INFO_PRINT(F("Run non blocking command: "));
INFO_PRINTLN(tCommandName);
#if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
} else {
/*
* Blocking command here
*/
if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) {
/*
* Here no blocking command was running and we are called from main loop
*/
requestToStopReceived = false; // Do not stop the command executed now
justCalledBlockingCommand = true;
currentBlockingCommandCalled = IRReceivedData.command; // set lock for recursive calls
lastBlockingCommandCalled = IRReceivedData.command; // set history, can be evaluated by main loop
/*
* This call is blocking!!!
*/
INFO_PRINT(F("Run blocking command: "));
INFO_PRINTLN(tCommandName);
#if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
TRACE_PRINTLN(F("End of blocking command"));
currentBlockingCommandCalled = COMMAND_EMPTY;
} else {
/*
* Called by ISR or another command still running.
* Do not run command directly, but set request to stop to true and store command
* for main loop to execute by checkAndRunSuspendedBlockingCommands()
*/
BlockingCommandToRunNext = IRReceivedData.command;
requestToStopReceived = true; // to stop running command
INFO_PRINT(F("Requested stop and stored blocking command "));
INFO_PRINT(tCommandName);
INFO_PRINTLN(F(" as next command to run."));
}
}
break; // command found
} // if (IRReceivedData.command == IRMapping[i].IRCode)
} // for loop
return;
}
/*
* Intended to be called from main loop
* @return true, if command was called
*/
bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() {
/*
* Take last rejected command and call associated function
*/
if (BlockingCommandToRunNext != COMMAND_EMPTY) {
INFO_PRINT(F("Run stored command=0x"));
INFO_PRINTLN(BlockingCommandToRunNext, HEX);
IRReceivedData.command = BlockingCommandToRunNext;
BlockingCommandToRunNext = COMMAND_EMPTY;
IRReceivedData.isRepeat = false;
requestToStopReceived = false; // Signal to main loop to stop the command currently executed
checkAndCallCommand(true);
return true;
}
return false;
}
/*
* Not used internally
*/
void IRCommandDispatcher::setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext) {
#if defined(LOCAL_INFO)
Serial.print(F("Set next command to run to 0x"));
Serial.print(aBlockingCommandToRunNext, HEX);
# if defined(USE_DISPATCHER_COMMAND_STRINGS)
Serial.print('|');
printIRCommandString(&Serial, aBlockingCommandToRunNext);
# endif
Serial.println();
#endif
BlockingCommandToRunNext = aBlockingCommandToRunNext;
requestToStopReceived = true;
}
/*
* Special delay function for the IRCommandDispatcher. Returns prematurely if requestToStopReceived is set.
* To be used in blocking functions as delay
* @return true - as soon as stop received
*/
bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) {
uint32_t tStartMillis = millis();
do {
if (requestToStopReceived) {
return true;
}
} while (millis() - tStartMillis < aDelayMillis);
return false;
}
void IRCommandDispatcher::printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex) {
#if defined(__AVR__)
# if defined(USE_DISPATCHER_COMMAND_STRINGS)
aSerial->println(reinterpret_cast(IRMapping[aMappingArrayIndex].CommandString));
# else
aSerial->print(F("0x"));
aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX);
# endif
#else
# if defined(USE_DISPATCHER_COMMAND_STRINGS)
aSerial->println(IRMapping[aMappingArrayIndex].CommandString);
# else
aSerial->print("0x");
aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX);
# endif
#endif
}
void IRCommandDispatcher::printIRCommandString(Print *aSerial, IRCommandType aCommand) {
for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
if (aCommand == IRMapping[i].IRCode) {
printIRCommandStringForArrayIndex(aSerial, i);
return;
}
}
aSerial->println(F("unknown"));
}
void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) {
requestToStopReceived = aRequestToStopReceived;
}
#include "LocalDebugLevelEnd.h"
#endif // _IR_COMMAND_DISPATCHER_HPP
================================================
FILE: src/IRFeedbackLED.h
================================================
/*
* IRFeedbackLED.h
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_.
#if defined(ARDUINO)
#ifndef _IR_FEEDBACK_LED_H
#define _IR_FEEDBACK_LED_H
// define it for convenience reasons. It is an empty function, if NO_LED_FEEDBACK_CODE is enabled
void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed); // set the mode
#if !defined(NO_LED_FEEDBACK_CODE)
/*
* Set IRMP_FEEDBACK_LED_PIN to a reasonable value
* defining it to 0 disables LED feedback function otherwise LED_BUILTIN (if available) is taken as feedback LED.
*/
#if !defined(IRMP_FEEDBACK_LED_PIN)
# if defined(LED_BUILTIN)
#define IRMP_FEEDBACK_LED_PIN LED_BUILTIN
# else
#warning IRMP_FEEDBACK_LED_PIN and LED_BUILTIN not defined. Pin 5 is used for feedback output if feedback is enabled. You can change this in IRFeedbackLED.h.
#define IRMP_FEEDBACK_LED_PIN 5 // choose an arbitrary pin
# endif
#endif
void irmp_irsnd_SetFeedbackLED(bool aSwitchLedOn); // set set pin
constexpr auto irmp_blink13 = irmp_irsnd_LEDFeedback; // alias for irmp_blink13
constexpr auto irmp_LEDFeedback = irmp_irsnd_LEDFeedback; // alias for irmp_LEDFeedback
constexpr auto irsnd_LEDFeedback = irmp_irsnd_LEDFeedback; // alias for irsnd_LEDFeedback
#endif // !defined(NO_LED_FEEDBACK_CODE)
#endif // _IR_FEEDBACK_LED_H
#endif // defined(ARDUINO)
================================================
FILE: src/IRFeedbackLED.hpp
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IRFeedbackLED.hpp - Arduino extensions for IR feedback LED handling
*
* Copyright (c) 2020-2021 Armin Joachimsmeyer
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IR_FEEDBACK_LED_HPP
#define _IR_FEEDBACK_LED_HPP
#if defined(ARDUINO)
#include "IRFeedbackLED.h"
#if defined(NO_LED_FEEDBACK_CODE)
// dummy void function in this case
void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed)
{
(void)aEnableBlinkLed;
}
#else // defined(NO_LED_FEEDBACK_CODE)
static bool irmp_irsnd_LedFeedbackEnabled;
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
// global variable to hold feedback led pin number. Set to 0 to not activating feedback LED by default.
uint_fast8_t irmp_irsnd_LedFeedbackPin = 0;
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
bool irmp_irsnd_LedFeedbackPinIsActiveLow = true; // global variable to hold feedback led polarity.
# else
bool irmp_irsnd_LedFeedbackPinIsActiveLow = false; // global variable to hold feedback led polarity.
# endif
#endif
/*
* Enable/disable echoing the input signal to the built in (or specified) LED.
*/
void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed)
{
#if defined(IRMP_FEEDBACK_LED_PIN) || defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
irmp_irsnd_LedFeedbackEnabled = aEnableBlinkLed;
if (aEnableBlinkLed)
{
# if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
pinMode(irmp_irsnd_LedFeedbackPin, OUTPUT);
if (irmp_irsnd_LedFeedbackPinIsActiveLow)
{
digitalWrite(irmp_irsnd_LedFeedbackPin, HIGH);
}
else
{
digitalWrite(irmp_irsnd_LedFeedbackPin, LOW);
}
# elif defined(IRMP_FEEDBACK_LED_PIN)
pinModeFast(IRMP_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW);
# endif
# endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
}
# if defined(ALLOW_DISABLE_FEEDBACK_LED_EXPLICIT)
else
{
/*
* Disable here
* normally this code is never used, since disabling is done by setting irmp_led_feedback to false.
*/
# if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
if(irmp_irsnd_LedFeedbackPin != 0) {
pinMode(irmp_irsnd_LedFeedbackPin, INPUT);
digitalWrite(irmp_irsnd_LedFeedbackPin, LOW); // to disable internal pullup
}
# else
pinModeFast(IRMP_FEEDBACK_LED_PIN, INPUT);
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW); // to disable internal pullup
# endif
}
# endif
#endif // defined(IRMP_FEEDBACK_LED_PIN) || defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
}
/*
* Internally used from IRMP_ISR() with -oS it is taken as inline function
*/
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void irmp_irsnd_SetFeedbackLED(bool aSwitchLedOn)
{
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
if(irmp_irsnd_LedFeedbackPin != 0) {
if (irmp_irsnd_LedFeedbackPinIsActiveLow)
{
digitalWrite(irmp_irsnd_LedFeedbackPin, !aSwitchLedOn);
}
else
{
digitalWrite(irmp_irsnd_LedFeedbackPin, aSwitchLedOn);
}
}
#elif defined(IRMP_FEEDBACK_LED_PIN)
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
// If the built in LED on the board is active LOW
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, !aSwitchLedOn);
# else
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, aSwitchLedOn);
# endif
#endif
}
#endif // !defined(NO_LED_FEEDBACK_CODE)
#endif // defined(ARDUINO)
#endif // _IR_FEEDBACK_LED_HPP
================================================
FILE: src/IRTimer.h
================================================
/*
* IRTimer.h
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
// NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_.
#if defined(ARDUINO)
#if ! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) && defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H)
#error You seem to use receive and send in one sketch but forget to define USE_ONE_TIMER_FOR_IRMP_AND_IRSND before the includes. Unfortunately this cannot be done automatically.
#endif
#if defined(_IRMP_H_)
void initIRTimerForReceive(void);
#endif
#if defined(_IRSND_H_)
extern void initIRTimerForSend(void);
#endif // defined(_IRSND_H_)
extern void irmp_timer_ISR(void);
extern void disableIRTimerInterrupt(void);
extern void enableIRTimerInterrupt(void);
extern void storeIRTimer(void);
extern void restoreIRTimer(void);
#endif // defined(ARDUINO)
================================================
FILE: src/IRTimer.hpp
================================================
/*
* IRTimer.hpp
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* We use IR timer (timer 2 for AVR) for receive and send. Both functions can be used alternating but not at the same time.
* For receive we initialize IR timer to generate interrupts at 10 to 20 kHz for calling irmp_ISR().
* For send we have 76 kHz to toggle output pin. The irsnd_ISR() call rate is 1/4 of IR signal toggle rate.
* For send, initIRTimer() is called at each irsnd_send_data().
* The current state of IR timer is stored by initIRTimer() and restored after sending.
* This enables us to set up IR timer for receiving and on calling irsnd_send_data() the IR timer is reconfigured for the duration of sending.
* Therefore no (non interrupt) receiving is possible during sending of data.
*/
// NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_.
#include "IRTimer.h"
#if !defined(TIMER_DECLARED)
#define TIMER_DECLARED
# if defined(ESP32)
static hw_timer_t *sReceiveAndSendInterruptTimer = nullptr;
// BluePill in 2 flavors see https://samuelpinches.com.au/3d-printer/cutting-through-some-confusion-on-stm32-and-arduino/
# elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark.
// STM32F1 architecture for "Generic STM32F103C series" from "STM32F1 Boards (Arduino_STM32)" of Arduino Board manager
// http://dan.drown.org/stm32duino/package_STM32duino_index.json
#include // 4 timers and 4. timer (4.channel) is used for tone()
/*
* Use timer 3 as IRMP timer.
* Timer 3 blocks PA6, PA7, PB0, PB1, so if you require one of them as tone() or Servo output, you must choose another timer.
*/
HardwareTimer sReceiveAndSendInterruptTimer(3);
# elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems.
// stm32 architecture for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager
// https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
#include
/*
* Use timer 4 as IRMP timer.
* Timer 4 blocks PB6, PB7, PB8, PB9, so if you require one of them as tone() or Servo output, you must choose another timer.
*/
# if defined(TIM4)
HardwareTimer sReceiveAndSendInterruptTimer(TIM4);
# else
HardwareTimer sReceiveAndSendInterruptTimer(TIM2);
# endif
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3
mbed::Ticker sReceiveAndSendInterruptTimer;
/*
* RP2040 based boards for pico core
* https://github.com/earlephilhower/arduino-pico
* https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
* Can use any pin for PWM, no timer restrictions
*/
#elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
#include "pico/time.h"
repeating_timer_t sReceiveAndSendInterruptTimer;
bool IRTimerInterruptHandlerHelper(repeating_timer_t*);
#elif defined(TEENSYDUINO)
// common for all Teensy
IntervalTimer sReceiveAndSendInterruptTimer;
# endif
#endif // TIMER_DECLARED
#if defined(_IRMP_H_)
// we compile for irmp
#undef IR_INTERRUPT_FREQUENCY
#define IR_INTERRUPT_FREQUENCY F_INTERRUPTS // define frequency for receive
#elif defined(_IRSND_H_)
// we compile for irsnd
#undef IR_INTERRUPT_FREQUENCY
#define IR_INTERRUPT_FREQUENCY IRSND_INTERRUPT_FREQUENCY // define frequency for send
#endif // defined(_IRMP_H_)
// The eclipse formatter has problems with // comments in undefined code blocks
// !!! Must be without trailing comment and closed by @formatter:on
// @formatter:off
#if defined(_IRMP_H_)
void initIRTimerForReceive(void)
#elif defined(_IRSND_H_)
void initIRTimerForSend(void)
#endif
{
#if defined(__AVR__)
// Use Timer 2
# if defined(__AVR_ATmega16__)
TCCR2 = _BV(WGM21) | _BV(CS21); // CTC mode, prescale by 8
OCR2 = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz
TCNT2 = 0;
TIMSK = _BV(OCIE2); // enable interrupt
# elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// Since the ISR takes 5 to 22 microseconds for ATtiny@16MHz only 16 and 8 MHz makes sense
# if defined(ARDUINO_AVR_DIGISPARK)
// standard Digispark settings use timer 1 for millis() and micros()
// Timer 0 has only 1 and 8 as useful prescaler
TCCR0A = 0; // must be set to zero before configuration!
# if (F_CPU / IR_INTERRUPT_FREQUENCY) > 256 // for 8 bit timer
OCR0A = OCR0B = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz
TCCR0B = _BV(CS01); // presc = 8
# else
OCR0A = OCR0B = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz
TCCR0B = _BV(CS00); // presc = 1 / no prescaling
# endif
TCCR0A = _BV(WGM01); // CTC with OCRA as top
TCNT0 = 0;
TIMSK |= _BV(OCIE0B); // enable compare match interrupt
# else
// Use timer 1
# if (F_CPU / IR_INTERRUPT_FREQUENCY) > 256 // for 8 bit timer
OCR1B = OCR1C = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz
TCCR1 = _BV(CTC1) | _BV(CS12); // switch CTC Mode on, set prescaler to 8
# else
OCR1B = OCR1C = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz
TCCR1 = _BV(CTC1) | _BV(CS10); // switch CTC Mode on, set prescaler to 1 / no prescaling
# endif
TCNT1 = 0;
TIMSK |= _BV(OCIE1B); // enable compare match interrupt
# endif
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
// Timer 1 is a 16 bit counter so we need no prescaler
ICR1 = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1065 for 15 kHz @16 MHz. compare value: 1/15000 of CPU frequency
TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10); // switch CTC Mode on, set prescaler to 1 / no prescaling
TCNT1 = 0;
TIMSK1 = _BV(OCIE1B); // enable compare match B interrupt, compare match A is used by tone library
# elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
// TCB1 is used by Tone()
// TCB2 is used by Servo
// TCB3 is used by millis()
TCB0.CTRLB = TCB_CNTMODE_INT_gc;
TCB0.CCMP = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz
TCB0.INTFLAGS = TCB_CAPT_bm; // reset interrupt flags
TCB0.INTCTRL = TCB_CAPT_bm; // enable capture compare interrupt
TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm;
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // TinyCore boards
// use one ramp mode and overflow interrupt
# if defined(MILLIS_USE_TIMERA0)
TCD0.CTRLA = 0; // reset enable bit in order to unprotect the other bits
TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; // must be set since it is used by PWM
// TCD0.CMPBSET = 80;
TCD0.CMPBCLR = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1332 for 15 kHz, 262 for 76000 interrupts per second @ 20MHz
// Generate 50% duty cycle signal for debugging etc.
// TCD0.CMPASET = 0;
// TCD0.CMPACLR = (F_CPU / (IR_INTERRUPT_FREQUENCY * 2)) - 1; // 50% duty cycle for WOA
// TCD0.CTRLC = 0; // reset WOx outputs
// _PROTECTED_WRITE(TCD0.FAULTCTRL,FUSE_CMPAEN_bm); // enable WOA signal
// PORTA.DIRSET = PIN4_bm; // enable WOA output pin 13/PA4
// _PROTECTED_WRITE(TCD0.FAULTCTRL,FUSE_CMPAEN_bm | FUSE_CMPBEN_bm); // enable WOA + WOB signal signal
// PORTA.DIRSET = PIN4_bm | PIN5_bm; // enable WOA + WOB output pins 13/PA4 + 14/PA5
TCD0.INTFLAGS = TCD_OVF_bm; // reset interrupt flags
TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt
// check enable ready
// while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required
// enable timer - this locks the other bits and static registers and activates values in double buffered registers
TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc| TCD_CNTPRES_DIV1_gc; // System clock, no prescale, no synchronization prescaler
# else
TCA0.SINGLE.CTRLD = 0; // Single mode - required at least for MegaTinyCore
TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc; // Normal mode, top = PER
TCA0.SINGLE.PER = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1332 for 15 kHz, 262 for 76000 interrupts per second @ 20MHz
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; // reset interrupt flags
TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; // overflow interrupt
// check enable ready
// while ((TCA0.SINGLE.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required
// enable timer - this locks the other bits and static registers and activates values in double buffered registers
TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV1_gc; // System clock
# endif
# elif defined(__AVR_ATmega8__)
# if (F_CPU / IR_INTERRUPT_FREQUENCY) <= 256 // for 8 bit timer
TCCR2 = _BV(WGM21) | _BV(CS20); // CTC mode, no prescale
OCR2 = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second
# else
TCCR2 = _BV(WGM21) | _BV(CS21); // CTC mode, prescale by 8
OCR2 = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz
# endif
TCNT2 = 0;
TIFR = _BV(OCF2) | _BV(TOV2); // reset interrupt flags
TIMSK = _BV(OCIE2); // enable TIMER2_COMP_vect interrupt to be compatible with tone() library
# elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
TCCR3A = 0;
TCCR3B = _BV(CS30) | _BV(WGM32); // no prescale, CTC mode Top OCR3A
// Set OCR3B = OCR3A since we use TIMER3_COMPB_vect as interrupt, but run timer in CTC mode with OCR3A as TOP
OCR3B = OCR3A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1065 for 15 kHz, 209 for 76 kHz @ 16MHz
TCNT3 = 0;
TIMSK3 = _BV(OCIE3B); // enable TIMER3_COMPB_vect interrupt to be compatible with tone() library
# elif defined(OCF2B) // __AVR_ATmega328__ here
TCCR2A = _BV(WGM21); // CTC mode
# if (F_CPU / IR_INTERRUPT_FREQUENCY) <= 256 // for 8 bit timer
TCCR2B = _BV(CS20); // no prescale
// Set OCR2B = OCR2A since we use TIMER2_COMPB_vect as interrupt, but run timer in CTC mode with OCR2A as TOP
OCR2B = OCR2A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second @ 16MHz
# else
TCCR2B = _BV(CS21); // prescale by 8
OCR2B = OCR2A = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz
# endif
TCNT2 = 0;
TIFR2 = _BV(OCF2B) | _BV(OCF2A) | _BV(TOV2); // reset interrupt flags
TIMSK2 = _BV(OCIE2B); // enable TIMER2_COMPB_vect interrupt to be compatible with tone() library
# elif defined(TCCR1B) // __AVR_ATtiny88__ here
TCCR1A = 0;
TCCR1B = _BV(WGM12) | _BV(CS10); // CTC mode, no prescaling
OCR1A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second @ 16MHz
TCNT1 = 0;
# if defined(TIMSK1)
TIMSK1 = _BV(OCIE1A); // Timer/Counter1, Output Compare A Match Interrupt Enable
# else // ATmega128 ?
TIMSK = _BV(OCIE1A); // Timer/Counter1, Output Compare A Match Interrupt Enable
# endif
# else // if defined(__AVR_ATmega16__) etc
#error "This AVR CPU is not supported by IRMP"
# endif // if defined(__AVR_ATmega16__)
#elif defined(ESP8266)
timer1_isr_init();
timer1_attachInterrupt(irmp_timer_ISR);
/*
* TIM_DIV1 = 0, //80MHz (80 ticks/us - 104857.588 us max)
* TIM_DIV16 = 1, //5MHz (5 ticks/us - 1677721.4 us max)
* TIM_DIV256 = 3 //312.5Khz (1 tick = 3.2us - 26843542.4 us max)
*/
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); // must be before timer1_write!
timer1_write(((80000000 / 16) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY); // 80000000 holds for 80 and 160 MHz clock!
#elif defined(ESP32)
// Tasmota requires timer 3 (last of 4 timers)
// Use timer with 1 microsecond resolution, main clock is 80MHZ
if(sReceiveAndSendInterruptTimer == nullptr) {
# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
sReceiveAndSendInterruptTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start.
timerAttachInterrupt(sReceiveAndSendInterruptTimer, irmp_timer_ISR);
timerAlarm(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true, 0); // 0 in the last parameter is repeat forever
# else
sReceiveAndSendInterruptTimer = timerBegin(3, 80, true);
timerAttachInterrupt(sReceiveAndSendInterruptTimer, irmp_timer_ISR, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-(
timerAlarmWrite(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true);
#endif
}
enableIRTimerInterrupt();
# if defined(DEBUG) && defined(ESP32)
Serial.print("CPU frequency=");
Serial.print(getCpuFrequencyMhz());
Serial.println("MHz");
Serial.print("Timer clock frequency=");
Serial.print(getApbFrequency());
Serial.println("Hz");
# endif
// BluePill in 2 flavors
#elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark.
// http://dan.drown.org/stm32duino/package_STM32duino_index.json
sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
sReceiveAndSendInterruptTimer.setPrescaleFactor(1);
sReceiveAndSendInterruptTimer.setOverflow(F_CPU / IR_INTERRUPT_FREQUENCY);
//sReceiveAndSendInterruptTimer.setPeriod(1000000 / IR_INTERRUPT_FREQUENCY);
sReceiveAndSendInterruptTimer.attachInterrupt(TIMER_CH1, irmp_timer_ISR);
sReceiveAndSendInterruptTimer.refresh(); // Set the timer's count to 0 and update the prescaler and overflow values.
#elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems.
// https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_OUTPUT_COMPARE, NC); // used for generating only interrupts, no pin specified
sReceiveAndSendInterruptTimer.setPrescaleFactor(1);
sReceiveAndSendInterruptTimer.setOverflow(F_CPU / IR_INTERRUPT_FREQUENCY, TICK_FORMAT); // clock cycles period
//sReceiveAndSendInterruptTimer.setOverflow(1000000 / IR_INTERRUPT_FREQUENCY, MICROSEC_FORMAT); // microsecond period
sReceiveAndSendInterruptTimer.attachInterrupt(irmp_timer_ISR); // this sets update interrupt enable
sReceiveAndSendInterruptTimer.resume(); // Start or resume HardwareTimer: all channels are resumed, interrupts are enabled if necessary
#elif defined(ARDUINO_ARCH_SAMD)
REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3); // GCLK1=32kHz, GCLK0=48MHz
// while (GCLK->STATUS.bit.SYNCBUSY) // not required to wait
// ;
TcCount16* TC = (TcCount16*) TC3;
TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; // Enable write access to CTRLA register
while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
// Set Timer counter Mode to 16 bits, use match mode so that the timer counter resets when the count matches the compare register
TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |TC_CTRLA_PRESCALER_DIV1;
TC->CC[0].reg = (uint16_t) ((F_CPU / IR_INTERRUPT_FREQUENCY) - 1); // ((48MHz / sampleRate) - 1);
// Enable the compare interrupt
TC->INTENSET.reg = 0;
TC->INTENSET.bit.MC0 = 1;
NVIC_EnableIRQ (TC3_IRQn);
TC->CTRLA.reg |= TC_CTRLA_ENABLE;
// while (TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY); // Not required to wait at end of function
//#elif defined(ARDUINO_ARCH_APOLLO3)
//// Use Timer 3 segment B
// am_hal_ctimer_clear(3, AM_HAL_CTIMER_TIMERB); // reset timer
//// only AM_HAL_CTIMER_FN_REPEAT resets counter after match (CTC mode)
// am_hal_ctimer_config_single(3, AM_HAL_CTIMER_TIMERB, (AM_HAL_CTIMER_INT_ENABLE | AM_HAL_CTIMER_HFRC_12MHZ | AM_HAL_CTIMER_FN_REPEAT));
// am_hal_ctimer_compare_set(3, AM_HAL_CTIMER_TIMERB, 0, 12000000 / IR_INTERRUPT_FREQUENCY);
// am_hal_ctimer_start(3, AM_HAL_CTIMER_TIMERB);
//
// am_hal_ctimer_int_register(AM_HAL_CTIMER_INT_TIMERB3, irmp_timer_ISR);
// am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERB3);
// NVIC_EnableIRQ(CTIMER_IRQn);
#elif defined(ARDUINO_ARCH_MBED)
sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY));
#elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc.
add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer); // 13.15 us
#elif defined(TEENSYDUINO)
sReceiveAndSendInterruptTimer.begin(irmp_timer_ISR, 1000000 / IR_INTERRUPT_FREQUENCY);
#endif // defined(__AVR__)
}
// @formatter:on
#if !defined(TIMER_FUNCTIONS_DEFINED)
#define TIMER_FUNCTIONS_DEFINED
/** Temporarily storage for timer register*/
#if defined(__AVR__)
uint8_t sTimerTCCRA;
uint8_t sTimerTCCRB;
# if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) \
|| defined(__AVR_ATtiny3217__) || defined(__AVR_ATmega4809__)
uint16_t sTimerOCR; // we have a 12/16 bit timer
# else
uint8_t sTimerOCR;
# endif
uint8_t sTimerOCRB;
uint8_t sTimerTIMSK;
#elif defined(ESP8266)
uint32_t sTimerLoadValue;
#elif defined(ESP32)
uint64_t sTimerAlarmValue;
#elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) || defined(__STM32F1__)
uint32_t sTimerOverflowValue;
#elif defined(ARDUINO_ARCH_SAMD) // || defined(ARDUINO_ARCH_APOLLO3)
uint16_t sTimerCompareCapureValue;
#endif // defined(__AVR__)
/*
* If we do not use receive, we have no timer defined at the first call of this function.
* But for AVR saving the timer settings is possible anyway, since it only consists of saving registers.
* This helps cooperation with other libraries using the same timer.
*/
void storeIRTimer(void) {
#if defined(__AVR_ATmega16__)
sTimerTCCRA = TCCR2;
sTimerOCR = OCR2;
sTimerTIMSK = TIMSK;
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
# if defined(ARDUINO_AVR_DIGISPARK)
sTimerTCCRA = TCCR0A;
sTimerTCCRB = TCCR0B;
sTimerOCRB = OCR0B;
sTimerOCR = OCR0A;
sTimerTIMSK = TIMSK;
# else
sTimerTCCRA = TCCR1;
sTimerOCRB = OCR1B;
sTimerOCR = OCR1C;
sTimerTIMSK = TIMSK;
# endif
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
sTimerTCCRB = TCCR1B;
sTimerOCR = ICR1;
sTimerOCRB = OCR1B;
sTimerTIMSK = TIMSK1;
#elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
// store current timer state
sTimerTCCRA = TCB0.CTRLA;
sTimerTCCRB = TCB0.CTRLB;
sTimerOCR = TCB0.CCMP;
sTimerTIMSK = TCB0.INTCTRL;
#elif defined(__AVR_ATmega8__)
sTimerTCCRA = TCCR2;
sTimerOCR = OCR2;
sTimerTIMSK = TIMSK;
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
// store current timer state
sTimerTCCRA = TCCR3A;
sTimerTCCRB = TCCR3B;
sTimerOCR = OCR3A;
sTimerOCRB = OCR3B;
sTimerTIMSK = TIMSK3;
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
// store settings used for PWM
# if defined(MILLIS_USE_TIMERA0)
sTimerTCCRA = TCD0.CTRLA;
sTimerTCCRB = TCD0.CTRLB;
sTimerOCR = TCD0.CMPBCLR;
sTimerOCRB = TCD0.CTRLC;
sTimerTIMSK = TCD0.INTCTRL;
# else
sTimerTCCRA = TCA0.SINGLE.CTRLA;
sTimerTCCRB = TCA0.SINGLE.CTRLB;
sTimerOCR = TCA0.SINGLE.PER;
sTimerOCRB = TCA0.SINGLE.CTRLC;
sTimerTIMSK = TCA0.SINGLE.INTCTRL;
# endif
#elif defined(OCF2B) // __AVR_ATmega328__ here
// store current timer state
sTimerTCCRA = TCCR2A;
sTimerTCCRB = TCCR2B;
sTimerOCR = OCR2A;
sTimerOCRB = OCR2B;
sTimerTIMSK = TIMSK2;
#elif defined(TCCR1B) // __AVR_ATtiny88__ here
// store current timer state
sTimerTCCRA = TCCR1A;
sTimerTCCRB = TCCR1B;
sTimerOCR = OCR1A;
sTimerOCRB = OCR1B;
# if defined(TIMSK1)
sTimerTIMSK = TIMSK1;
# else
sTimerTIMSK = TIMSK;
# endif
#elif defined(__AVR__)
// #error "This AVR CPU is not supported by IRMP"
#elif defined(ESP8266)
sTimerLoadValue= T1L;
#endif // defined(__AVR_ATmega16__)
#if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
// If we do not use receive, we have no timer defined at the first call of this function
# if defined(ESP32)
# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
sTimerAlarmValue = timerAlarmRead(sReceiveAndSendInterruptTimer);
# endif
# elif defined(STM32F1xx)
sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow(TICK_FORMAT);
# elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx
sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow(TICK_FORMAT);
# elif defined(__STM32F1__)
sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow();
# elif defined(ARDUINO_ARCH_SAMD)
sTimerCompareCapureValue = TC3->COUNT16.CC[0].reg;
//# elif defined(ARDUINO_ARCH_APOLLO3)
// sTimerCompareCapureValue = *((uint32_t *)CTIMERADDRn(CTIMER, 3, CMPRB0)) & 0xFFFF;
# endif
#endif // defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
}
/*
* Restore settings of the timer e.g. for IRSND
*/
void restoreIRTimer(void) {
#if defined(__AVR_ATmega16__)
TCCR2 = sTimerTCCRA;
OCR2 = sTimerOCR;
TIMSK = sTimerTIMSK;
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
# if defined(ARDUINO_AVR_DIGISPARK)
TCCR0A = sTimerTCCRA;
TCCR0B = sTimerTCCRB;
OCR0B = sTimerOCRB;
OCR0A = sTimerOCR;
TIMSK = sTimerTIMSK;
# else
TCCR1 = sTimerTCCRA;
OCR1B = sTimerOCRB;
OCR1C = sTimerOCR;
TIMSK = sTimerTIMSK;
# endif
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
TCCR1B = sTimerTCCRB;
ICR1 = sTimerOCR;
OCR1B = sTimerOCRB;
TIMSK1 = sTimerTIMSK;
#elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
TCB0.CTRLA = sTimerTCCRA;
TCB0.CTRLB = sTimerTCCRB;
TCB0.CCMP = sTimerOCR;
TCB0.INTCTRL = sTimerTIMSK;
#elif defined(__AVR_ATmega8__)
TCCR2 = sTimerTCCRA;
OCR2 = sTimerOCR;
TIMSK = sTimerTIMSK;
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
// restore current timer state
TCCR3A = sTimerTCCRA;
TCCR3B = sTimerTCCRB;
OCR3A = sTimerOCR;
OCR3B = sTimerOCRB;
TIMSK3 = sTimerTIMSK;
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
// restore settings used for PWM
# if defined(MILLIS_USE_TIMERA0)
TCD0.CTRLA = 0; // unlock timer
TCD0.CTRLB = sTimerTCCRB;
TCD0.CMPBCLR = sTimerOCR;
TCD0.CTRLC = sTimerOCRB;
TCD0.INTCTRL = sTimerTIMSK;
TCD0.CTRLA = sTimerTCCRA;
# else
TCA0.SINGLE.CTRLA = 0; // unlock timer
TCA0.SINGLE.CTRLB = sTimerTCCRB;
TCA0.SINGLE.PER = sTimerOCR;
TCA0.SINGLE.CTRLC = sTimerOCRB;
TCA0.SINGLE.INTCTRL = sTimerTIMSK;
TCA0.SINGLE.CTRLA = sTimerTCCRA;
# endif
#elif defined(OCF2B) // __AVR_ATmega328__ here
TCCR2A = sTimerTCCRA;
TCCR2B = sTimerTCCRB;
OCR2A = sTimerOCR;
OCR2B = sTimerOCRB;
TIMSK2 = sTimerTIMSK;
#elif defined(TCCR1B) // __AVR_ATtiny88__ here
// store current timer state
TCCR1A = sTimerTCCRA;
TCCR1B = sTimerTCCRB;
OCR1A = sTimerOCR;
OCR1B = sTimerOCRB;
# if defined(TIMSK1)
TIMSK1 = sTimerTIMSK;
# else
TIMSK = sTimerTIMSK;
# endif
#elif defined(__AVR__)
// #error "This AVR CPU is not supported by IRMP"
#elif defined(ESP8266)
timer1_write(sTimerLoadValue);
#endif // defined(__AVR_ATmega16__)
#if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
# if defined(ESP32)
# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
// we have no timerAlarmRead, so we just initialize timer again.
timerAlarm(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true, 0); // 0 in the last parameter is repeat forever
# else
timerAlarmWrite(sReceiveAndSendInterruptTimer, sTimerAlarmValue, true);
# endif
# elif defined(STM32F1xx)
sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue, TICK_FORMAT);
# elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx
sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue, TICK_FORMAT);
# elif defined(__STM32F1__)
sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue);
# elif defined(ARDUINO_ARCH_SAMD)
TC3->COUNT16.CC[0].reg = sTimerCompareCapureValue;
//# elif defined(ARDUINO_ARCH_APOLLO3)
// am_hal_ctimer_compare_set(3, AM_HAL_CTIMER_TIMERB, 0, sTimerCompareCapureValue);
# elif defined(ARDUINO_ARCH_MBED)
sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY));
#elif defined(ARDUINO_ARCH_RP2040)
add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer);
# elif defined(TEENSYDUINO)
sReceiveAndSendInterruptTimer.update(1000000 / IR_INTERRUPT_FREQUENCY);
# endif
#endif // defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
}
/*
* NOT used if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined
* Initialize timer to generate interrupts at a rate F_INTERRUPTS (15000) per second to poll the input pin.
*/
void disableIRTimerInterrupt(void) {
#if defined(__AVR__)
// Use Timer 2
# if defined(__AVR_ATmega16__)
TIMSK = 0; // disable interrupt
# elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
# if defined(ARDUINO_AVR_DIGISPARK)
TIMSK &= ~_BV(OCIE0B); // disable interrupt
# else
TIMSK &= ~_BV(OCIE1B); // disable interrupt
# endif
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
TIMSK1 &= ~_BV(OCIE1A); // disable interrupt
#elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
TCB0.INTCTRL &= ~TCB_CAPT_bm;
#elif defined(__AVR_ATmega8__)
TIMSK &= ~_BV(OCIE2); // disable interrupt
# elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
TIMSK3 = 0; // disable interrupt
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
# if defined(MILLIS_USE_TIMERA0)
TCD0.INTCTRL = 0; // overflow interrupt
# else
TCA0.SINGLE.INTCTRL = 0; // overflow interrupt
# endif
# elif defined(OCF2B) // __AVR_ATmega328__ here
TIMSK2 = 0; // disable interrupt
# elif defined(TCCR1B) // __AVR_ATtiny88__ here
# if defined(TIMSK1)
TIMSK1 = 0;
# else
TIMSK = 0;
# endif
# else
// #error "This AVR CPU is not supported by IRMP"
# endif // defined(__AVR_ATmega16__)
#elif defined(ESP8266)
timer1_detachInterrupt(); // disables interrupt too
#elif defined(ESP32)
if (sReceiveAndSendInterruptTimer != nullptr) {
# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
timerStop(sReceiveAndSendInterruptTimer);
# else
timerAlarmDisable(sReceiveAndSendInterruptTimer);
# endif
}
#elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems.
sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_DISABLED);
sReceiveAndSendInterruptTimer.detachInterrupt();
#elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark.
sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_DISABLED);
sReceiveAndSendInterruptTimer.detachInterrupt(TIMER_CH1);
#elif defined(ARDUINO_ARCH_SAMD)
TC3->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
// while (TC3->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY) ; // Not required to wait at end of function
//#elif defined(ARDUINO_ARCH_APOLLO3)
// am_hal_ctimer_int_disable(AM_HAL_CTIMER_INT_TIMERB3);
#elif defined(ARDUINO_ARCH_MBED)
sReceiveAndSendInterruptTimer.detach();
#elif defined(ARDUINO_ARCH_RP2040)
cancel_repeating_timer(&sReceiveAndSendInterruptTimer);
#elif defined(TEENSYDUINO)
sReceiveAndSendInterruptTimer.end();
#endif // defined(__AVR__)
}
// used by AllProtocols example
void enableIRTimerInterrupt(void) {
#if defined(__AVR__)
// Use Timer 2
# if defined(__AVR_ATmega16__)
TIMSK = _BV(OCIE2); // enable interrupt
# elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
# if defined(ARDUINO_AVR_DIGISPARK)
TIMSK |= _BV(OCIE0B); // enable compare match interrupt
# else
TIMSK |= _BV(OCIE1B); // enable compare match interrupt
# endif
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
TIMSK1 |= _BV(OCIE1A); // enable compare match interrupt
#elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
TCB0.INTCTRL = TCB_CAPT_bm;
#elif defined(__AVR_ATmega8__)
TIMSK = _BV(OCIE2); // enable interrupt
# elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
TIMSK3 = _BV(OCIE3B); // enable interrupt
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
# if defined(MILLIS_USE_TIMERA0)
TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt
# else
TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; // overflow interrupt
# endif
# elif defined(OCF2B) // __AVR_ATmega328__ here
TIMSK2 = _BV(OCIE2B); // enable interrupt
# elif defined(TCCR1B) // __AVR_ATtiny88__ here
# if defined(TIMSK1)
TIMSK1 = _BV(OCIE1A);
# else
TIMSK = _BV(OCIE1A);
# endif
# else
// #error "This AVR CPU is not supported by IRMP"
# endif // defined(__AVR_ATmega16__)
#elif defined(ESP8266)
timer1_attachInterrupt(irmp_timer_ISR); // enables interrupt too
#elif defined(ESP32)
if (sReceiveAndSendInterruptTimer != nullptr) {
# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically
timerStart(sReceiveAndSendInterruptTimer);
# else
timerAlarmEnable(sReceiveAndSendInterruptTimer);
# endif
}
#elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark.
// http://dan.drown.org/stm32duino/package_STM32duino_index.json
sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
sReceiveAndSendInterruptTimer.attachInterrupt(TIMER_CH1, irmp_timer_ISR);
sReceiveAndSendInterruptTimer.refresh(); // Set the timer's count to 0 and update the prescaler and overflow values.
#elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems.
// https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_OUTPUT_COMPARE, NC); // used for generating only interrupts, no pin specified
sReceiveAndSendInterruptTimer.attachInterrupt(irmp_timer_ISR);
sReceiveAndSendInterruptTimer.refresh();// Set the timer's count to 0 and update the prescaler and overflow values.
#elif defined(ARDUINO_ARCH_SAMD)
TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;
while (TC3->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY)
; //wait until TC5 is done syncing
//#elif defined(ARDUINO_ARCH_APOLLO3)
// am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERB3);
#elif defined(ARDUINO_ARCH_MBED)
sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY));
#elif defined(ARDUINO_ARCH_RP2040)
add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer);
#elif defined(TEENSYDUINO)
sReceiveAndSendInterruptTimer.begin(irmp_timer_ISR, 1000000 / IR_INTERRUPT_FREQUENCY);
#else
#warning Board / CPU is not covered by definitions using pre-processor symbols -> no timer available. Please extend IRTimer.hpp.
#endif // defined(__AVR__)
}
#endif // TIMER_FUNCTIONS_DEFINED
/*
* If both irmp and irsnd are used, compile it only once in the second step, when all variables are declared.
*/
#if (! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) || ( defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H) )) && ! defined(ISR_DEFINED)
# if !defined(ISR_DEFINED)
#define ISR_DEFINED
# endif
/*
* ISR is active while signal is sent AND during the trailing pause of IR frame
* Called every 13.5us
* Bit bang requires 5.9 us. 5 us for 16 push and 16 pop etc. and 0.9 us for function body
* Together with call of irsnd_ISR() 10.5 us (frame) or 9.4 (trailing pause) - measured by scope
* We use TIMER2_COMPB_vect to be compatible with tone() library
*/
#if defined(__AVR__)
# if F_CPU < 8000000L
#error F_CPU must not be less than 8MHz for IRMP and IRSND
# endif
# if defined(__AVR_ATmega16__)
ISR(TIMER2_COMP_vect)
# elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARK)
ISR(TIMER0_COMPB_vect)
# else
ISR(TIMER1_COMPB_vect)
# endif
# elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
ISR(TCB0_INT_vect)
# elif defined(__AVR_ATmega8__)
ISR(TIMER2_COMP_vect)
# elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc.
ISR(TIMER3_COMPB_vect)
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
# if defined(MILLIS_USE_TIMERA0)
ISR(TCD0_OVF_vect)
# else
ISR(TCA0_OVF_vect)
# endif
# elif defined(OCF2B) // __AVR_ATmega328__ here
ISR(TIMER2_COMPB_vect)
# elif defined(TCCR1B) // __AVR_ATtiny88__ here
ISR(TIMER1_COMPB_vect)
# else
// #error "This AVR CPU is not supported by IRMP"
# endif // defined(__AVR_ATmega16__)
#elif defined(ESP8266) || defined(ESP32)
void IRAM_ATTR irmp_timer_ISR(void)
#elif defined(ARDUINO_ARCH_SAMD)
void TC3_Handler(void)
#elif defined(STM32F1xx) && STM32_CORE_VERSION_MAJOR == 1 && STM32_CORE_VERSION_MINOR <= 8 // for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager
void irmp_timer_ISR(HardwareTimer *aDummy __attribute__((unused))) // old 1.8 version - changed in stm32duino 1.9 - 5/2020
#elif defined(ARDUINO_ARCH_RP2040)
void irmp_timer_ISR(void);
bool IRTimerInterruptHandlerHelper(repeating_timer_t*) { // we are called with a different signature
irmp_timer_ISR();
return true;
}
void irmp_timer_ISR(void)
#else // STM32F1xx (v1.9), __STM32F1__, ARDUINO_ARCH_APOLLO3, MBED, TEENSYDUINO
void irmp_timer_ISR(void)
#endif // defined(__AVR__)
// Start of ISR
{
#if defined(ARDUINO_ARCH_SAMD)
TC3->COUNT16.INTFLAG.bit.MC0 = 1; // Clear interrupt
#endif
#if defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every
// Not tested, but with the experience, I made with the ATtiny3217, I guess it is required
TCB0.INTFLAGS = TCB_CAPT_bm; // reset interrupt flags
#endif
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
// must reset interrupt flag here
# if defined(MILLIS_USE_TIMERA0)
TCD0.INTFLAGS = TCD_OVF_bm;
# else
TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm;
# endif
#endif
#if (defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND))
static uint8_t sDivider; // IR signal toggle rate is 2 (4) times IRSND call rate
#endif
#if defined(IRMP_MEASURE_TIMING) && defined(IR_TIMING_TEST_PIN)
digitalWriteFast(IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
#if defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
/*
* Send part of ISR
*/
if(irsnd_busy) {
if (irsnd_is_on)
{
# if defined(IRSND_GENERATE_NO_SEND_RF)
// output is active low
if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);}
# else
if(sDivider & 0x01) // true / inactive if sDivider is 3 or 1, so we start with active and end with inactive
{
if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);}
} else {
if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);}
}
# endif // defined(IRSND_GENERATE_NO_SEND_RF)
} else {
// irsnd off here
if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);}
}
/*
* Call irsnd_ISR() every second (fourth) call if current LED state is inactive
*/
if (--sDivider == 0)
{
// This in turn calls irsnd_on() or irsnd_off(). Empty call requires additional 0.7 us.
if (!irsnd_ISR())
{
// End of frame
restoreIRTimer();
# if ! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
// only send mode required -> disable interrupt
disableIRTimerInterrupt();
# endif
sDivider = 1; // to call irsnd_ISR() directly at next interrupt
} else {
sDivider = 4;
}
}
} // if(irsnd_busy)
#endif // defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
#if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
else
{ // for receive and send in one ISR
#endif
#if defined(_IRMP_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
/*
* Receive part of ISR
*/
irmp_ISR();
#endif
#if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)
} // for receive and send in one ISR
#endif
#if defined(IRMP_MEASURE_TIMING) && defined(IR_TIMING_TEST_PIN)
digitalWriteFast(IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
#endif
}
#endif // (! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) || ( defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H) )) && ! defined(ISR_DEFINED)
================================================
FILE: src/LocalDebugLevelEnd.h
================================================
/*
* LocalDebugLevelEnd.h
* Undefine local macros at the end of an included (.hpp) file
*
* Copyright (C) 2024 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* Arduino-Utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public INFOse for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/*
* Undefine local macros at the end of an included (.hpp) file
*/
#if defined(LOCAL_TRACE)
#undef LOCAL_TRACE
#endif
#undef TRACE_PRINT
#undef TRACE_PRINTLN
#undef TRACE_FLUSH
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#undef DEBUG_PRINT
#undef DEBUG_PRINTLN
#undef DEBUG_FLUSH
#if defined(LOCAL_INFO)
#undef LOCAL_INFO
#endif
#undef INFO_PRINT
#undef INFO_PRINTLN
#undef INFO_FLUSH
================================================
FILE: src/LocalDebugLevelStart.h
================================================
/*
* LocalDebugLevelStart.h
* Include to propagate global debug levels to file local ones and to define appropriate print macros.
* !!! If used in included (.hpp) files, #include "LocalDebugLevelEnd.h" must be used at end of file to undefine local macros.
* If, for example, #define LOCAL_TRACE is placed before this include, it will not be propagated. This enables TRACE-level output to be selected only.
*
* LOCAL_TRACE // Information you need to understand details of a function or if you hunt a bug.
* LOCAL_DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables.
* LOCAL_INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody".
* LOCAL_WARN // Information that the program may encounter problems, like small Heap/Stack area.
* LOCAL_ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects.
*
* Copyright (C) 2024-2026 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* Arduino-Utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public INFOse for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
/////////////// put this before the include /////////////////////////
// This block must be located after the includes of other *.hpp files
//#define LOCAL_INFO // This enables info output only for this file
//#define LOCAL_DEBUG // This enables debug output only for this file - only for development
//#define LOCAL_TRACE // This enables trace output only for this file - only for development
/*
* Propagate debug level to local ones but at first not to each other, i.e. enabling TRACE does not enable DEBUG and INFO
*/
#if defined(TRACE) // Information you need to understand details of a function or if you hunt a bug.
#define LOCAL_TRACE
# if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS) // Propagate levels by default i.e. enabling TRACE does enable DEBUG and INFO
#define LOCAL_DEBUG
#define LOCAL_INFO
# endif
#endif
#if defined(DEBUG) // Information need to understand the operating of your program. E.g. function calls and values of control variables.
#define LOCAL_DEBUG
# if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS)
#define LOCAL_INFO
# endif
#endif
#if defined(INFO) // Information you want to see in regular operation to see what the program is doing. E.g. "START ../src/LightToTone.cpp Version 1.2 from Dec 31 2019" or "Now playing Muppets melody".
#define LOCAL_INFO
#endif
/*
* Define appropriate print macros
*/
#if defined(LOCAL_TRACE)
#define TRACE_PRINT(...) Serial.print(__VA_ARGS__)
#define TRACE_PRINTLN(...) Serial.println(__VA_ARGS__)
#define TRACE_FLUSH() Serial.flush()
#else
#define TRACE_PRINT(...) void()
#define TRACE_PRINTLN(...) void()
#define TRACE_FLUSH() void()
#endif
#if defined(LOCAL_DEBUG)
#define DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
#define DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
#define DEBUG_FLUSH() Serial.flush()
#else
#define DEBUG_PRINT(...) void()
#define DEBUG_PRINTLN(...) void()
#define DEBUG_FLUSH() void()
#endif
#if defined(LOCAL_INFO)
#define INFO_PRINT(...) Serial.print(__VA_ARGS__)
#define INFO_PRINTLN(...) Serial.println(__VA_ARGS__)
#define INFO_FLUSH() Serial.flush()
#else
#define INFO_PRINT(...) void()
#define INFO_PRINTLN(...) void()
#define INFO_FLUSH() void()
#endif
================================================
FILE: src/LongUnion.h
================================================
/*
* LongUnion.h
*
* Copyright (C) 2020-2022 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
*
* Arduino-Utils is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#if !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H)
#include
#ifndef _WORD_UNION_H
#define _WORD_UNION_H
/**
* Union to specify parts / manifestations of a 16 bit Word without casts and shifts.
* It also supports the compiler generating small code.
* Usage: WordUnion tWord;
* tWord.UByte.HighByte = 0x12;
*/
union WordUnion {
struct {
uint8_t LowByte;
uint8_t HighByte;
} UByte;
struct {
int8_t LowByte;
int8_t HighByte;
} Byte;
uint8_t UBytes[2]; // UBytes[0] is LowByte
int8_t Bytes[2];
uint16_t UWord;
int16_t Word;
uint8_t *BytePointer;
};
#endif // _WORD_UNION_H
#ifndef _LONG_UNION_H
#define _LONG_UNION_H
/**
* Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
* It also supports the compiler generating small code.
*/
union LongUnion {
struct {
uint8_t LowByte;
uint8_t MidLowByte;
uint8_t MidHighByte;
uint8_t HighByte;
} UByte;
struct {
int8_t LowByte;
int8_t MidLowByte;
int8_t MidHighByte;
int8_t HighByte;
} Byte;
/* Does not work for STM32
struct {
uint8_t LowByte;
uint16_t MidWord;
uint8_t HighByte;
} UByteWord;
*/
struct {
uint16_t LowWord;
uint16_t HighWord;
} UWord;
struct {
int16_t LowWord;
int16_t HighWord;
} Word;
struct {
WordUnion LowWord;
WordUnion HighWord;
} TwoWordUnions;
uint8_t UBytes[4]; // seems to have the same code size as using struct UByte
int8_t Bytes[4]; // Bytes[0] is LowByte
uint16_t UWords[2];
int16_t Words[2];
uint32_t ULong;
int32_t Long;
float Float;
};
#endif // _LONG_UNION_H
#ifndef _LONG_LONG_UNION_H
#define _LONG_LONG_UNION_H
/**
* Union to specify parts / manifestations of a 64 bit LongLong without casts and shifts.
* It also supports the compiler generating small code.
*/
union LongLongUnion {
struct {
uint16_t LowWord;
uint16_t MidLowWord;
uint16_t MidHighWord;
uint16_t HighWord;
} UWord;
struct {
int16_t LowWord;
int16_t MidLowWord;
int16_t MidHighWord;
int16_t HighWord;
} Word;
struct {
WordUnion LowWord;
WordUnion MidLowWord;
WordUnion MidHighWord;
WordUnion HighWord;
} FourWordUnions;
struct {
uint32_t LowLong;
uint32_t HighLong;
} ULong;
struct {
int32_t LowLong;
int32_t HighLong;
} Long;
struct {
LongUnion LowLong;
LongUnion HighLong;
} TwoLongUnions;
uint8_t UBytes[8]; // seems to have the same code size as using struct UByte
int8_t Bytes[8];
uint16_t UWords[4];
int16_t Words[4];
uint64_t ULongLong;
int64_t LongLong;
#if __DBL_MANT_DIG__== 24
float Floats[2]; // 32 bit double, as for AVR
#else
// 64 bit double
double Double;
#endif
};
#endif // _LONG_LONG_UNION_H
#endif // !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H)
================================================
FILE: src/TinyIR.h
================================================
/*
* TinyIR.h
*
*
* Copyright (C) 2021-2025 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
* This file is also part of IRMP https://github.com/IRMP-org/IRMP.
*
* TinyIRReceiver is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef _TINY_IR_H
#define _TINY_IR_H
#include
#include "LongUnion.h"
/** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol
* @{
*/
#define VERSION_TINYIR "2.3.0"
#define VERSION_TINYIR_MAJOR 2
#define VERSION_TINYIR_MINOR 3
#define VERSION_TINYIR_PATCH 0
// The change log is at the bottom of the file
/**
* Timing for NEC protocol
*
* see: https://www.sbprojects.net/knowledge/ir/nec.php
* LSB first, 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit.
*/
#if !defined(NEC_ADDRESS_BITS)
#define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
#define NEC_COMMAND_BITS 16 // Command and inverted command
#define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
#define NEC_UNIT 560
#define NEC_HEADER_MARK (16 * NEC_UNIT) // 8860
#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4480
#define NEC_BIT_MARK NEC_UNIT
#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1680
#define NEC_ZERO_SPACE NEC_UNIT
#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2240
#define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
#define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
#define NEC_MAXIMUM_REPEAT_DISTANCE (NEC_REPEAT_PERIOD - NEC_MINIMAL_DURATION + 10000) // 70 ms
#endif
/**
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*/
/*
Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+2100,-1050
+ 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
+ 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550
+ 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
+ 550
Sum: 28900
*/
#define FAST_KHZ 38
#define FAST_ADDRESS_BITS 0 // No address
#define FAST_COMMAND_BITS 16 // Command and inverted command (parity)
#define FAST_BITS (FAST_ADDRESS_BITS + FAST_COMMAND_BITS)
#define FAST_UNIT 526 // 20 periods of 38 kHz (526.315789)
#define FAST_BIT_MARK FAST_UNIT
#define FAST_ONE_SPACE (3 * FAST_UNIT) // 1578 -> bit period = 2104
#define FAST_ZERO_SPACE FAST_UNIT // 526 -> bit period = 1052
#define FAST_HEADER_MARK (4 * FAST_UNIT) // 2104
#define FAST_HEADER_SPACE (2 * FAST_UNIT) // 1052
#define FAST_REPEAT_PERIOD 50000 // Commands are repeated every 50 ms (measured from start to start) for as long as the key on the remote control is held down.
#define FAST_REPEAT_DISTANCE (FAST_REPEAT_PERIOD - (55 * FAST_UNIT)) // 19 ms
#define FAST_MAXIMUM_REPEAT_DISTANCE (FAST_REPEAT_DISTANCE + 10000) // 29 ms
/*
* Definitions to switch between FAST and NEC/ONKYO timing with the same code.
*/
#if defined(USE_FAST_PROTOCOL)
#define ENABLE_NEC2_REPEATS // Disables detection of special short frame NEC repeats. Saves 40 bytes program memory.
#define TINY_RECEIVER_ADDRESS_BITS FAST_ADDRESS_BITS
#define TINY_RECEIVER_COMMAND_BITS FAST_COMMAND_BITS
#if !defined(TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY)
#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
//#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity - not tested
#endif
#define TINY_RECEIVER_BITS FAST_BITS
#define TINY_RECEIVER_UNIT FAST_UNIT
#define TINY_RECEIVER_HEADER_MARK FAST_HEADER_MARK
#define TINY_RECEIVER_HEADER_SPACE FAST_HEADER_SPACE
#define TINY_RECEIVER_MARK_TIMEOUT (2 * FAST_HEADER_MARK)
#define TINY_RECEIVER_BIT_MARK FAST_BIT_MARK
#define TINY_RECEIVER_ONE_SPACE FAST_ONE_SPACE
#define TINY_RECEIVER_ZERO_SPACE FAST_ZERO_SPACE
#define TINY_RECEIVER_ONE_THRESHOLD (2 * FAST_UNIT) // 1052
#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE FAST_MAXIMUM_REPEAT_DISTANCE // for repeat detection
#else
#define TINY_RECEIVER_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity
# if defined(USE_ONKYO_PROTOCOL)
#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity
# elif defined(USE_EXTENDED_NEC_PROTOCOL)
#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity
# else
#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
# endif
#define TINY_RECEIVER_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity
# if defined(USE_ONKYO_PROTOCOL)
#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity
# else
#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
# endif
#define TINY_RECEIVER_BITS NEC_BITS
#define TINY_RECEIVER_UNIT NEC_UNIT
#define TINY_RECEIVER_HEADER_MARK NEC_HEADER_MARK
#define TINY_RECEIVER_MARK_TIMEOUT (2 * NEC_HEADER_MARK)
#define TINY_RECEIVER_HEADER_SPACE NEC_HEADER_SPACE
#define TINY_RECEIVER_BIT_MARK NEC_BIT_MARK
#define TINY_RECEIVER_ONE_SPACE NEC_ONE_SPACE
#define TINY_RECEIVER_ZERO_SPACE NEC_ZERO_SPACE
#define TINY_RECEIVER_ONE_THRESHOLD (2 * NEC_UNIT) // 1120
#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE
#endif
#if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
/*
* This function is called, if a complete command was received and must be implemented in the file (user code)
* which includes this library if USE_CALLBACK_FOR_TINY_RECEIVER is activated.
*/
extern void handleReceivedTinyIRData();
#endif
#if !defined(MICROS_IN_ONE_SECOND)
#define MICROS_IN_ONE_SECOND 1000000L
#endif
#if !defined(MICROS_IN_ONE_MILLI)
#define MICROS_IN_ONE_MILLI 1000L
#endif
/*
* Macros for comparing timing values
*/
#define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4))
#define upperValue25Percent(aDuration) (aDuration + (aDuration / 4))
#define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2))
#define upperValue50Percent(aDuration) (aDuration + (aDuration / 2))
/*
* The states for the state machine
*/
#define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0
#define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1
#define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4
#define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5
/**
* Control and data variables of the state machine for TinyIRReceiver
*/
struct TinyIRReceiverStruct {
/*
* State machine
*/
uint32_t LastChangeMicros; ///< Microseconds of last Pin Change Interrupt.
uint8_t IRReceiverState; ///< The state of the state machine.
uint8_t IRRawDataBitCounter; ///< How many bits are currently contained in raw data.
/*
* Data
*/
#if (TINY_RECEIVER_BITS > 16)
uint32_t IRRawDataMask; ///< The corresponding bit mask for IRRawDataBitCounter.
LongUnion IRRawData; ///< The current raw data. LongUnion helps with decoding of address and command.
#else
uint16_t IRRawDataMask; ///< The corresponding bit mask for IRRawDataBitCounter.
WordUnion IRRawData; ///< The current raw data. WordUnion helps with decoding of command.
#endif
uint8_t Flags; ///< One of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT, and IRDATA_FLAGS_PARITY_FAILED
};
/*
* Definitions for member TinyIRReceiverCallbackDataStruct.Flags
* This is a copy of flags from IRremoteInt.h
*/
#define IRDATA_FLAGS_EMPTY 0x00
#define IRDATA_FLAGS_IS_REPEAT 0x01
#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used for TinyIR
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
/**
* Is filled before calling the user callback to transfer received data to main loop for further processing.
*/
struct TinyIRReceiverCallbackDataStruct {
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
# if (TINY_RECEIVER_ADDRESS_BITS == 16) && !TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
uint16_t Address;
# else
uint8_t Address;
# endif
#endif
# if (TINY_RECEIVER_COMMAND_BITS == 16) && !TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
uint16_t Command;
#else
uint8_t Command;
#endif
uint8_t Flags; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED
bool justWritten; ///< Is set true if new data is available. Used by the main loop / TinyIRReceiverDecode(), to avoid multiple evaluations of the same IR frame.
};
extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
bool isIRReceiverAttachedForTinyReceiver();
bool initPCIInterruptForTinyReceiver();
bool enablePCIInterruptForTinyReceiver();
void disablePCIInterruptForTinyReceiver();
bool isTinyReceiverIdle();
bool TinyReceiverDecode();
void printTinyReceiverResultMinimal(Print *aSerial);
bool isIRReceiverAttachedForTinyIRReceiver();
bool initPCIInterruptForTinyIRReceiver();
bool enablePCIInterruptForTinyIRReceiver();
void disablePCIInterruptForTinyIRReceiver();
bool isTinyIRReceiverIdle();
bool TinyIRReceiverDecode();
void printTinyIRReceiverResultMinimal(Print *aSerial);
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0);
void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0);
void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100
void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0)
__attribute__ ((deprecated ("Renamed to sendNEC().")));
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
#if defined(NO_LED_FEEDBACK_CODE)
# if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
#define NO_LED_RECEIVE_FEEDBACK_CODE
# endif
# if !defined(NO_LED_SEND_FEEDBACK_CODE)
#define NO_LED_SEND_FEEDBACK_CODE
# endif
#endif
#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
#define IR_FEEDBACK_LED_PIN LED_BUILTIN
#endif
/*
* Version 2.3.0 - 3/2026
* - Renamed TinyReceiver*() functions to TinyIRReceiver*().
*
* Version 2.2.0 - 7/2024
* - New TinyReceiverDecode() function to be used as drop in for IrReceiver.decode().
*
* Version 2.1.0 - 2/2024
* - New sendExtendedNEC() function and new parameter aSendNEC2Repeats.
*
* Version 2.0.0 - 10/2023
* - New TinyIRReceiverData which is filled with address, command and flags.
* - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal().
* - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated.
*
* Version 1.2.0 - 01/2023
* - Added ONKYO protocol, NEC with 16 bit address and command, instead of 8 bit + 8 bit parity address and command.
* - Renamed functions and macros.
*
* Version 1.1.0 - 01/2023
* - FAST protocol added.
*/
/** @}*/
#endif // _TINY_IR_H
================================================
FILE: src/TinyIRReceiver.hpp
================================================
/*
* TinyIRReceiver.hpp
*
* Receives IR data of NEC protocol using pin change interrupts.
* NEC is the protocol of most cheap remote controls for Arduino.
*
* Parity check is done for address and data.
* On a completely received IR command, the user function handleReceivedIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags)
* is called in interrupt context but with interrupts being enabled to enable use of delay() etc.
* !!!!!!!!!!!!!!!!!!!!!!
* Functions called in interrupt context should be running as short as possible,
* so if you require longer action, save the data (address + command) and handle them in the main loop.
* !!!!!!!!!!!!!!!!!!!!!
* aFlags can contain one of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bits
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
* This file is also part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2026 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
/*
* This library can be configured at compile time by the following options / macros:
* For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down)
*
* - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input.
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function for send and receive. Saves 14 bytes program memory.
* - NO_LED_RECEIVE_FEEDBACK_CODE Disables the LED feedback code for receive.
* - NO_LED_SEND_FEEDBACK_CODE Disables the LED feedback code for send.
* - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory.
* - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_ONKYO_PROTOCOL Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC.
* - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
* - USE_CALLBACK_FOR_TINY_RECEIVER Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
*/
#ifndef _TINY_IR_RECEIVER_HPP
#define _TINY_IR_RECEIVER_HPP
#include
/*
* Protocol selection
*/
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define IR_RECEIVE_PIN 2
//#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN
#include "TinyIR.h"
#include "digitalWriteFast.h"
/** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol
* @{
*/
// This block must be located after the includes of other *.hpp files
//#define LOCAL_DEBUG // This enables debug output only for this file - only for development
//#define LOCAL_TRACE // This enables trace output only for this file - only for development
#include "LocalDebugLevelStart.h"
#if defined(LOCAL_DEBUG)
#define LOCAL_DEBUG_ATTACH_INTERRUPT
#else
//#define LOCAL_DEBUG_ATTACH_INTERRUPT // To see if attachInterrupt() or static interrupt (by register tweaking) is used and no other debug output
#endif
//#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement.
//#define _IR_TIMING_TEST_PIN 7
TinyIRReceiverStruct TinyIRReceiverControl;
volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; // The persistent copy of all IR data after receiving a complete frame. To be used by main program.
/*
* Set input pin and output pin definitions etc.
*/
#if defined(IR_INPUT_PIN)
#warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
#define IR_RECEIVE_PIN IR_INPUT_PIN
#endif
#if !defined(IR_RECEIVE_PIN)
# if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
#define IR_RECEIVE_PIN 10
# elif defined(__AVR_ATtiny816__)
#warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
#define IR_RECEIVE_PIN 14
# else
#warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
#define IR_RECEIVE_PIN 2
# endif
#endif
#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
#define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
#endif
#if !( \
(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \
|| defined(__AVR_ATtiny88__) /* MH-ET LIVE Tiny88 */ \
|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
|| defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
|| defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
/* ATmegas with ports 0,1,2 above and ATtiny167 only 2 pins below */ \
|| ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\
|| (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \
)
/*
* Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change.
* Requires additional 112 bytes program memory + 4 bytes RAM
*/
#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
#endif
/**
* Declaration of the callback function provided by the user application.
* It is called every time a complete IR command or repeat was received.
*/
extern void handleReceivedTinyIRData();
uint32_t sMicrosOfGap; // The length of the gap before the start bit, used for trace
/**
* The ISR (Interrupt Service Routine) of TinyIRRreceiver.
* It handles the NEC protocol decoding and calls the user callback function on complete.
* 5 us + 3 us for push + pop for a 16MHz ATmega
*/
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void IRPinChangeInterruptHandler(void) {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
/*
* Save IR input level
* Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark.
*/
uint_fast8_t tIRLevel = digitalReadFast(IR_RECEIVE_PIN);
#if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, tIRLevel);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, !tIRLevel);
# endif
#endif
/*
* 1. compute microseconds after last change
*/
// Repeats can be sent after a pause, which is longer than 64000 microseconds, so we need a 32 bit value for check of repeats
uint32_t tCurrentMicros = micros();
uint32_t tMicrosOfMarkOrSpace32 = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros; // statement is required to force 32 bit arithmetic
uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;
uint8_t tState = TinyIRReceiverControl.IRReceiverState;
TRACE_PRINT(tState);
TRACE_PRINT(F(" D="));
TRACE_PRINT(tMicrosOfMarkOrSpace);
// TRACE_PRINT(F(" I="));
// TRACE_PRINT(tIRLevel);
TRACE_PRINT('|');
if (tIRLevel == LOW) {
/*
* We are at the start of a mark here and tMicrosOfMarkOrSpace is the time of the previous space
*/
if (tMicrosOfMarkOrSpace > TINY_RECEIVER_MARK_TIMEOUT) {
// timeout -> must reset state machine
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) {
// We are at the beginning of the header mark, check timing at the next transition
tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
TinyIRReceiverControl.Flags = IRDATA_FLAGS_EMPTY; // If we do it here, it saves 4 bytes
#if defined(TRACE) // Do not use LOCAL_TRACE here since sMicrosOfGap is read in a cpp file at TRACE
sMicrosOfGap = tMicrosOfMarkOrSpace32;
#endif
#if defined(ENABLE_NEC2_REPEATS)
// Check for repeat, where full frame is sent again after TINY_RECEIVER_REPEAT_PERIOD ms
// Not required for NEC, where repeats are detected by a special header space duration
// Must use 32 bit arithmetic here!
if (tMicrosOfMarkOrSpace32 < TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE) {
TinyIRReceiverControl.Flags = IRDATA_FLAGS_IS_REPEAT;
}
#endif
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) {
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_SPACE)) {
/*
* We had a valid data header space before -> initialize data
*/
TinyIRReceiverControl.IRRawDataBitCounter = 0;
#if (TINY_RECEIVER_BITS > 16)
TinyIRReceiverControl.IRRawData.ULong = 0;
#else
TinyIRReceiverControl.IRRawData.UWord = 0;
#endif
TinyIRReceiverControl.IRRawDataMask = 1;
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
#if !defined(ENABLE_NEC2_REPEATS)
// Alternatively check for NEC repeat header space length
} else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS) {
/*
* We have a repeat header here and no broken receive before -> set repeat flag
*/
TinyIRReceiverControl.Flags = IRDATA_FLAGS_IS_REPEAT;
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
#endif
} else {
// This parts are optimized by the compiler into jumps to one code :-)
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
/*
* Start of data mark here, check data space length
* Maybe the minimum length check could be removed here.
*/
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_ZERO_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_ONE_SPACE)) {
// We have a valid bit here
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
if (tMicrosOfMarkOrSpace >= TINY_RECEIVER_ONE_THRESHOLD) {
// we received a 1
#if (TINY_RECEIVER_BITS > 16)
TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
#else
TinyIRReceiverControl.IRRawData.UWord |= TinyIRReceiverControl.IRRawDataMask;
#endif
} else {
// we received a 0 - empty code for documentation
}
// prepare for next bit
TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1;
TinyIRReceiverControl.IRRawDataBitCounter++;
} else {
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
} else {
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else {
/*
* We are at the start of a space here and tMicrosOfMarkOrSpace is the time of the previous mark
*
*/
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
/*
* Check length of header mark here
*/
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_MARK)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_MARK)) {
tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK;
} else {
// Wrong length of header mark -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) {
// Check data mark length
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_BIT_MARK)
&& tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_BIT_MARK)) {
/*
* We have a valid mark here, check for transmission complete, i.e. the mark of the stop bit
*/
if (TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS
#if !defined(ENABLE_NEC2_REPEATS)
|| (TinyIRReceiverControl.Flags & IRDATA_FLAGS_IS_REPEAT) // Do not check for full length received, if we have a short repeat frame
#endif
) {
/*
* Code complete -> optionally check parity
*/
// Reset state for new start
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
#if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
/*
* Check address parity
* Address is sent first and contained in the lower word
*/
if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) {
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set
#else
TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; // here we do not check anything, if we have a repeat
#endif
}
#endif
#if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
/*
* Check command parity
*/
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) {
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
#else
TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED;
#endif
DEBUG_PRINT(F("Parity check for command failed. Command="));
DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[2], HEX);
DEBUG_PRINT(F(" parity="));
DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[3], HEX);
#else
// No address, so command and parity are in the lowest bytes
if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) {
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
DEBUG_PRINT(F("Parity check for command failed. Command="));
DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[0], HEX);
DEBUG_PRINT(F(" parity="));
DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[1], HEX);
#endif
}
#endif
/*
* Call user provided callback here
* The parameter size is dependent of the code variant used in order to save program memory.
* We have 6 cases: 0, 8 bit or 16 bit address, each with 8 or 16 bit command
*/
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled
interrupts(); // enable interrupts, so delay() etc. works in callback
#endif
TinyIRReceiverData.justWritten = true;
TinyIRReceiverData.Flags = TinyIRReceiverControl.Flags;
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
// Here we have 8 bit address
TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UBytes[0];
# else
// Here we have 16 bit address
TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UWord.LowWord;
# endif
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
// Here we have 8 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[2];
# else
// Here we have 16 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord.HighWord;
# endif
#else
// Here we have NO address
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
// Here we have 8 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[0];
# else
// Here we have 16 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord;
# endif
#endif
#if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
handleReceivedTinyIRData();
#endif
} else {
// not finished yet
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK;
}
} else {
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
} else {
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
}
TinyIRReceiverControl.IRReceiverState = tState;
#ifdef _IR_MEASURE_TIMING
digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
#endif
}
bool isTinyIRReceiverIdle() {
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
}
bool isTinyReceiverIdle() {
return isTinyIRReceiverIdle();
}
/*
* Function to be used as drop in for IrReceiver.decode()
*/
bool TinyIRReceiverDecode() {
bool tJustWritten = TinyIRReceiverData.justWritten;
if (tJustWritten) {
TinyIRReceiverData.justWritten = false;
}
return tJustWritten;
}
bool TinyReceiverDecode() {
return TinyIRReceiverDecode();
}
/*
* Checks if IR_RECEIVE_PIN is connected and high
* @return true, if IR Receiver is attached
*/
bool isIRReceiverAttachedForTinyIRReceiver() {
pinModeFast(IR_RECEIVE_PIN, OUTPUT);
digitalWriteFast(IR_RECEIVE_PIN, LOW); // discharge pin capacity
pinModeFast(IR_RECEIVE_PIN, INPUT);
return digitalRead(IR_RECEIVE_PIN); // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast.
}
bool isIRReceiverAttachedForTinyReceiver() {
return isIRReceiverAttachedForTinyIRReceiver();
}
/**
* Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode.
* Then call enablePCIInterruptForTinyIRReceiver()
*/
bool initPCIInterruptForTinyIRReceiver() {
pinModeFast(IR_RECEIVE_PIN, INPUT);
#if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# endif
#endif
return enablePCIInterruptForTinyReceiver();
}
bool initPCIInterruptForTinyReceiver() {
return initPCIInterruptForTinyIRReceiver();
}
void printTinyIRReceiverResultMinimal(Print *aSerial) {
// Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
#if defined(USE_FAST_PROTOCOL)
aSerial->print(F("C=0x"));
#else
aSerial->print(F("A=0x"));
aSerial->print(TinyIRReceiverData.Address, HEX);
aSerial->print(F(" C=0x"));
#endif
aSerial->print(TinyIRReceiverData.Command, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
aSerial->print(F(" R"));
}
#if !defined(DISABLE_PARITY_CHECKS)
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
aSerial->print(F(" P"));
}
#endif
aSerial->println();
}
void printTinyReceiverResultMinimal(Print *aSerial) {
printTinyIRReceiverResultMinimal(aSerial);
}
#if !defined(STR_HELPER) && !defined(STR)
// Helper macro for getting a macro definition as string
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
/**************************************************
* Pin to interrupt mapping for different platforms
**************************************************/
#if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define USE_ATTACH_INTERRUPT_DIRECT
#elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
// Default for all NON AVR platforms
#define USE_ATTACH_INTERRUPT
#else
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define USE_PCIE
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_RECEIVE_PIN == 3)
#define USE_INT0
# elif (IR_RECEIVE_PIN == 9)
#define USE_INT1
# else
# error "IR_RECEIVE_PIN must be 9 or 3."
# endif // if (IR_RECEIVE_PIN == 9)
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IR_RECEIVE_PIN == 14)
#define USE_INT0
# elif (IR_RECEIVE_PIN == 3)
#define USE_INT1
# else
# error "IR_RECEIVE_PIN must be 14 or 3."
# endif // if (IR_RECEIVE_PIN == 14)
# endif
# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
# if (IR_RECEIVE_PIN == 21)
#define USE_INT0
# elif (IR_RECEIVE_PIN == 20)
#define USE_INT1
# else
#warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
#define USE_ATTACH_INTERRUPT
# endif
# else // defined(__AVR_ATtiny25__)
/*
* ATmegas + ATtiny88 here
*/
# if (IR_RECEIVE_PIN == 2)
#define USE_INT0
# elif (IR_RECEIVE_PIN == 3)
#define USE_INT1
# elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
#define USE_PCINT2
# elif IR_RECEIVE_PIN == 8 || IR_RECEIVE_PIN == 9 || IR_RECEIVE_PIN == 10 || IR_RECEIVE_PIN == 11 || IR_RECEIVE_PIN == 12 || IR_RECEIVE_PIN == 13
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
#define USE_PCINT0
# elif IR_RECEIVE_PIN == A0 || IR_RECEIVE_PIN == A1 || IR_RECEIVE_PIN == A2 || IR_RECEIVE_PIN == A3 || IR_RECEIVE_PIN == A4 || IR_RECEIVE_PIN == A5
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
#define USE_PCINT1
# else
#warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
#define USE_ATTACH_INTERRUPT
# endif // if (IR_RECEIVE_PIN == 2)
# endif // defined(__AVR_ATtiny25__)
#endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
/**
* Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt() function.
* @return true if interrupt was successfully enabled
*/
bool enablePCIInterruptForTinyIRReceiver() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
#if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
# if defined(USE_ATTACH_INTERRUPT)
# if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt
if(digitalPinToInterrupt(IR_RECEIVE_PIN) == NOT_AN_INTERRUPT){
return false;
}
# endif
// costs 112 bytes program memory + 4 bytes RAM
# if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here :-(
# else
attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), IRPinChangeInterruptHandler, CHANGE); // CHANGE can be an enum :-(
# endif
# else
// USE_ATTACH_INTERRUPT_DIRECT here, only defined for ATtinies *16, see above
// 2.2 us more than version configured with macros and not compatible
attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here
# endif
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
Serial.println(F("Use attachInterrupt for pin=" STR(IR_RECEIVE_PIN)));
# endif
#else
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
Serial.println(F("Use hardware/static interrupt for pin=" STR(IR_RECEIVE_PIN)));
# endif
# if defined(USE_INT0)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif defined(USE_INT1)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# elif defined(USE_PCIE) // For ATtiny85 etc.
// use PinChangeInterrupt no INT0 for pin PB2
PCMSK = _BV(IR_RECEIVE_PIN);
// clear interrupt bit
GIFR |= 1 << PCIF;
// enable interrupt on next change
GIMSK |= 1 << PCIE;
# elif defined(USE_PCINT0)
PCICR |= _BV(PCIE0);
PCMSK0 = digitalPinToBitMask(IR_RECEIVE_PIN);
# elif defined(USE_PCINT1)
PCICR |= _BV(PCIE1);
PCMSK1 = digitalPinToBitMask(IR_RECEIVE_PIN);
# elif defined(USE_PCINT2)
PCICR |= _BV(PCIE2);
PCMSK2 = digitalPinToBitMask(IR_RECEIVE_PIN);
# else
return false;
# endif
#endif // defined(USE_ATTACH_INTERRUPT)
return true;
}
bool enablePCIInterruptForTinyReceiver() {
return enablePCIInterruptForTinyIRReceiver();
}
void disablePCIInterruptForTinyIRReceiver() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
#if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
# if defined(USE_ATTACH_INTERRUPT)
detachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN));
# else
detachInterrupt(IR_RECEIVE_PIN);
# endif
#else
# if defined(USE_INT0)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~(1 << INT0);
# elif defined(USE_INT1)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# elif defined(USE_PCIE) // For ATtiny85 etc.
// clear interrupt bit
GIFR |= 1 << PCIF;
// disable interrupt on next change
GIMSK &= ~(1 << PCIE);
# elif defined(USE_PCINT0)
PCICR &= ~(_BV(PCIE0));
# elif defined(USE_PCINT1)
PCICR &= ~(_BV(PCIE1));
# elif defined(USE_PCINT2)
PCICR &= ~(_BV(PCIE2));
# endif
#endif // defined(USE_ATTACH_INTERRUPT)
}
void disablePCIInterruptForTinyReceiver() {
disablePCIInterruptForTinyIRReceiver();
}
/*
* Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores.
* The default value of TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT is set in TinyIRReceiver.h
*/
#if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
# if defined(USE_INT0)
ISR(INT0_vect)
# elif defined(USE_INT1)
ISR(INT1_vect)
# elif defined(USE_PCIE) // For ATtiny85 etc.
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
ISR(PCINT0_vect)
# elif defined(USE_PCINT0)
ISR(PCINT0_vect)
# elif defined(USE_PCINT1)
ISR(PCINT1_vect)
# elif defined(USE_PCINT2)
ISR(PCINT2_vect)
# else
void dummyFunctionToAvoidCompilerErrors()
# endif
{
IRPinChangeInterruptHandler();
}
#endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
/** @}*/
#if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
#undef LOCAL_DEBUG_ATTACH_INTERRUPT
#endif
#include "LocalDebugLevelEnd.h"
#endif // _TINY_IR_RECEIVER_HPP
================================================
FILE: src/TinyIRSender.hpp
================================================
/*
* TinyIRSender.hpp
*
* Sends IR protocol data of NEC and FAST protocol using bit banging.
* NEC is the protocol of most cheap remote controls for Arduino.
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
* - Bit timing is like NEC or JVC
* - The header is shorter, 3156 vs. 12500
* - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command,
* leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms.
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance.
*
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
* This file is also part of IRMP https://github.com/IRMP-org/IRMP.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2026 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#ifndef _TINY_IR_SENDER_HPP
#define _TINY_IR_SENDER_HPP
#include
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
//#define NO_LED_SEND_FEEDBACK_CODE // Disables the LED feedback code for receive.
//#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN
#include "TinyIR.h" // Defines protocol timings
#include "digitalWriteFast.h"
/** \addtogroup TinySender Minimal sender for NEC and FAST protocol
* @{
*/
#if !defined(IR_SEND_PIN)
#warning "IR_SEND_PIN is not defined, so it is set to 3"
#define IR_SEND_PIN 3
#endif
#if !defined(NO_LED_SEND_FEEDBACK_CODE)
#define LED_SEND_FEEDBACK_CODE // Resolve the double negative
#endif
/*
* Generate 38 kHz IR signal by bit banging and using delayMicroseconds() and micros()
*/
void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) {
unsigned long tMicros = micros();
unsigned long tNextPeriodEnding = tMicros;
#if defined(F_CPU)
unsigned long tEndMicros = tMicros + (112 / (F_CPU / MICROS_IN_ONE_SECOND)) + aMarkMicros; // To compensate for call duration - 112 is an empirical value
#else
unsigned long tEndMicros = tMicros + aMarkMicros;
#endif
do {
/*
* Generate pulse
*/
noInterrupts(); // do not let interrupts extend the short on period
digitalWriteFast(aSendPin, HIGH);
delayMicroseconds(8); // 8 us for a 30 % duty cycle for 38 kHz
digitalWriteFast(aSendPin, LOW);
interrupts(); // Enable interrupts - to keep micros correct- for the longer off period 3.4 us until receive ISR is active (for 7 us + pop's)
/*
* PWM pause timing and end check
* Minimal pause duration is 4.3 us
*/
tNextPeriodEnding += 26; // 26.3 us period for 38 kHz; 26 us -> 38.48 kHz
do {
tMicros = micros(); // we have only 4 us resolution for AVR @16MHz
/*
* Exit the forever loop if aMarkMicros has reached
*/
if (tMicros >= tEndMicros) {
return;
}
} while (tMicros < tNextPeriodEnding);
} while (true);
}
/*
* Send NEC with 16 bit address and command, even if aCommand < 0x100 (I.E. ONKYO)
* @param aAddress - The 16 bit address to send.
* @param aCommand - The 16 bit command to send.
* @param aNumberOfRepeats - Number of repeats send at a period of 110 ms.
* @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat.
*/
void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# endif
#endif
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
tData.UWord.LowWord = aAddress;
tData.UWord.HighWord = aCommand;
// Send data
for (uint_fast8_t i = 0; i < NEC_BITS; ++i) {
sendMark(aSendPin, NEC_BIT_MARK); // constant mark length
if (tData.ULong & 1) {
delayMicroseconds (NEC_ONE_SPACE);
} else {
delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
} // send stop bit
sendMark(aSendPin, NEC_BIT_MARK);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
/*
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) {
delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis);
}
}
}
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# endif
#endif
}
/*
* Send NEC with 8 or 16 bit address or command depending on the values of aAddress and aCommand.
* @param aAddress - If aAddress < 0x100 send 8 bit address and 8 bit inverted address, else send 16 bit address.
* @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command.
* @param aNumberOfRepeats - Number of repeats send at a period of 110 ms.
* @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat.
*/
void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendNEC(aSendPin, aAddress, aCommand, aNumberOfRepeats); // sendNECMinimal() is deprecated
}
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# endif
#endif
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
/*
* The compiler is intelligent and removes the code for "(aAddress > 0xFF)" if we are called with an uint8_t address :-).
* Using an uint16_t address requires additional 28 bytes program memory.
*/
if (aAddress > 0xFF) {
tData.UWord.LowWord = aAddress;
} else {
tData.UByte.LowByte = aAddress; // LSB first
tData.UByte.MidLowByte = ~aAddress;
}
if (aCommand > 0xFF) {
tData.UWord.HighWord = aCommand;
} else {
tData.UByte.MidHighByte = aCommand;
tData.UByte.HighByte = ~aCommand; // LSB first
}
// Send data
for (uint_fast8_t i = 0; i < NEC_BITS; ++i) {
sendMark(aSendPin, NEC_BIT_MARK); // constant mark length
if (tData.ULong & 1) {
delayMicroseconds (NEC_ONE_SPACE);
} else {
delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
} // send stop bit
sendMark(aSendPin, NEC_BIT_MARK);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
/*
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) {
delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis);
}
}
}
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# endif
#endif
}
/*
* Send Extended NEC with a forced 16 bit address and 8 or 16 bit command depending on the value of aCommand.
* @param aAddress - Send 16 bit address.
* @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command.
* @param aNumberOfRepeats - Number of repeats send at a period of 110 ms.
* @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat.
*/
void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# endif
#endif
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
tData.UWord.LowWord = aAddress;
if (aCommand > 0xFF) {
tData.UWord.HighWord = aCommand;
} else {
tData.UByte.MidHighByte = aCommand;
tData.UByte.HighByte = ~aCommand; // LSB first
}
// Send data
for (uint_fast8_t i = 0; i < NEC_BITS; ++i) {
sendMark(aSendPin, NEC_BIT_MARK); // constant mark length
if (tData.ULong & 1) {
delayMicroseconds (NEC_ONE_SPACE);
} else {
delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
} // send stop bit
sendMark(aSendPin, NEC_BIT_MARK);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
/*
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) {
delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis);
}
}
}
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# endif
#endif
}
/*
* LSB first, send header, command, inverted command and stop bit
*/
void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) {
sendFAST(aSendPin, aCommand, aNumberOfRepeats);
}
/*
* LSB first, send header, 16 bit command or 8 bit command, inverted command and stop bit
*/
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) {
pinModeFast(aSendPin, OUTPUT);
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# endif
#endif
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
// send header
sendMark(aSendPin, FAST_HEADER_MARK);
delayMicroseconds(FAST_HEADER_SPACE);
uint16_t tData;
/*
* The compiler is intelligent and removes the code for "(aCommand > 0xFF)" if we are called with an uint8_t command :-).
* Using an uint16_t command requires additional 56 bytes program memory.
*/
if (aCommand > 0xFF) {
tData = aCommand;
} else {
tData = aCommand | (((uint8_t) (~aCommand)) << 8); // LSB first
}
// Send data
for (uint_fast8_t i = 0; i < FAST_BITS; ++i) {
sendMark(aSendPin, FAST_BIT_MARK); // constant mark length
if (tData & 1) {
delayMicroseconds(FAST_ONE_SPACE);
} else {
delayMicroseconds(FAST_ZERO_SPACE);
}
tData >>= 1; // shift command for next bit
}
// send stop bit
sendMark(aSendPin, FAST_BIT_MARK);
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
/*
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
if (FAST_REPEAT_PERIOD / 1000 > tFrameDurationMillis) {
delay(FAST_REPEAT_PERIOD / 1000 - tFrameDurationMillis);
}
}
}
#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
# endif
#endif
}
/** @}*/
#endif // _TINY_IR_SENDER_HPP
================================================
FILE: src/digitalWriteFast.h
================================================
/*
* digitalWriteFast.h
*
* Optimized digital functions for AVR microcontrollers
* by Watterott electronic (www.watterott.com)
* based on https://code.google.com/p/digitalwritefast
*
* The value of DigitalReadFast() is the content of the input register e.g. 0x04 for pin2 and NOT always 0 or 1.
*
* License: BSD 3-Clause License (https://opensource.org/licenses/BSD-3-Clause)
*/
#ifndef __digitalWriteFast_h_
#define __digitalWriteFast_h_ 1
//#define THROW_ERROR_IF_NOT_FAST // If activated, an error is thrown if pin is not a compile time constant
void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") ));
void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") ));
void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") ));
int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") ));
#if !defined(MEGATINYCORE) // megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast().
//#define SANGUINO_PINOUT // define for Sanguino pinout
// general macros/defines
#if !defined(BIT_READ)
# define BIT_READ(value, bit) ((value) & (1UL << (bit)))
#endif
#if !defined(BIT_SET)
# define BIT_SET(value, bit) ((value) |= (1UL << (bit)))
#endif
#if !defined(BIT_CLEAR)
# define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit)))
#endif
#if !defined(BIT_WRITE)
# define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit))
#endif
#include // declarations for the fallback to digitalWrite(), digitalRead() etc.
// --- Arduino Mega and ATmega128x/256x based boards ---
#if (defined(ARDUINO_AVR_MEGA) || \
defined(ARDUINO_AVR_MEGA1280) || \
defined(ARDUINO_AVR_MEGA2560) || \
defined(__AVR_ATmega1280__) || \
defined(__AVR_ATmega1281__) || \
defined(__AVR_ATmega2560__) || \
defined(__AVR_ATmega2561__))
#define __digitalPinToPortReg(P) \
(((P) >= 22 && (P) <= 29) ? &PORTA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \
(((P) >= 30 && (P) <= 37) ? &PORTC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \
((((P) <= 3) || (P) == 5) ? &PORTE : \
(((P) >= 54 && (P) <= 61) ? &PORTF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \
(((P) == 14 || (P) == 15) ? &PORTJ : \
(((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL))))))))))
#define __digitalPinToDDRReg(P) \
(((P) >= 22 && (P) <= 29) ? &DDRA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \
(((P) >= 30 && (P) <= 37) ? &DDRC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \
((((P) <= 3) || (P) == 5) ? &DDRE : \
(((P) >= 54 && (P) <= 61) ? &DDRF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \
(((P) == 14 || (P) == 15) ? &DDRJ : \
(((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL))))))))))
#define __digitalPinToPINReg(P) \
(((P) >= 22 && (P) <= 29) ? &PINA : \
((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \
(((P) >= 30 && (P) <= 37) ? &PINC : \
((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \
((((P) <= 3) || (P) == 5) ? &PINE : \
(((P) >= 54 && (P) <= 61) ? &PINF : \
((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \
((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \
(((P) == 14 || (P) == 15) ? &PINJ : \
(((P) >= 62 && (P) <= 69) ? &PINK : &PINL))))))))))
#define __digitalPinToBit(P) \
(((P) >= 7 && (P) <= 9) ? (P) - 3 : \
(((P) >= 10 && (P) <= 13) ? (P) - 6 : \
(((P) >= 22 && (P) <= 29) ? (P) - 22 : \
(((P) >= 30 && (P) <= 37) ? 37 - (P) : \
(((P) >= 39 && (P) <= 41) ? 41 - (P) : \
(((P) >= 42 && (P) <= 49) ? 49 - (P) : \
(((P) >= 50 && (P) <= 53) ? 53 - (P) : \
(((P) >= 54 && (P) <= 61) ? (P) - 54 : \
(((P) >= 62 && (P) <= 69) ? (P) - 62 : \
(((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \
(((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \
(((P) == 19) ? 2 : \
(((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \
(((P) == 2) ? 4 : \
(((P) == 3 || (P) == 4) ? 5 : 7)))))))))))))))
// --- Arduino MightyCore standard pinout ---
#elif (defined(__AVR_ATmega1284P__) || \
defined(__AVR_ATmega1284__) || \
defined(__AVR_ATmega644P__) || \
defined(__AVR_ATmega644A__) || \
defined(__AVR_ATmega644__) || \
defined(__AVR_ATmega324PB__) || \
defined(__AVR_ATmega324PA__) || \
defined(__AVR_ATmega324P__) || \
defined(__AVR_ATmega324A__) || \
defined(__AVR_ATmega164P__) || \
defined(__AVR_ATmega164A__) || \
defined(__AVR_ATmega32__) || \
defined(__AVR_ATmega16__) || \
defined(__AVR_ATmega8535__)) && \
!defined(BOBUINO_PINOUT)
#if defined(__AVR_ATmega324PB__)
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE))))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE))))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE))))
# if defined(SANGUINO_PINOUT)
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (7 - ((P) - 24)) : (P) - 32))))
# else //MightyCore Pinout
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (P) - 24 : (P) - 32))))
# endif
#elif defined(PORTA)
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA)))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : &DDRA)))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : &PINA)))
# if defined(SANGUINO_PINOUT)
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24)))))
# else //MightyCore Pinout
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24)))
# endif
#else
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : &PORTC))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : &DDRC))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : &PINC))
# if defined(SANGUINO_PINOUT)
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24)))))
# else //MightyCore Pinout
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24)))
# endif
#endif
// --- Arduino Leonardo and ATmega16U4/32U4 based boards ---
#elif (defined(ARDUINO_AVR_LEONARDO) || \
defined(__AVR_ATmega16U4__) || \
defined(__AVR_ATmega32U4__))
# if defined(TEENSYDUINO)
#define __digitalPinToPortReg(P) \
((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PORTB : (((P) == 9 || (P) == 10) ? &PORTC : (((P) >= 16 && (P) <= 21)) ? &PORTF : &PORTD))
#define __digitalPinToDDRReg(P) \
((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &DDRB : (((P) == 9 || (P) == 10) ? &DDRC : (((P) >= 16 && (P) <= 21)) ? &DDRF : &DDRD))
#define __digitalPinToPINReg(P) \
((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PINB : (((P) == 9 || (P) == 10) ? &PINC : (((P) >= 16 && (P) <= 21)) ? &PINF : &PIND))
#define __digitalPinToBit(P) \
(((P) <= 3) ? (P) : \
(((P) == 4 || (P) == 12) ? 7 : \
(((P) <= 8) ? (P) - 5 : \
(((P) <= 10) ? (P) - 3 : \
(((P) == 11) ? 6 : \
(((P) <= 15) ? (P) - 9 : \
(((P) <= 19) ? 23 - (P) : \
(((P) <= 21) ? 21 - (P) : (P) - 18))))))))
# else
#define __digitalPinToPortReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PORTD : (((P) == 5 || (P) == 13) ? &PORTC : (((P) >= 18 && (P) <= 23)) ? &PORTF : (((P) == 7) ? &PORTE : &PORTB)))
#define __digitalPinToDDRReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &DDRD : (((P) == 5 || (P) == 13) ? &DDRC : (((P) >= 18 && (P) <= 23)) ? &DDRF : (((P) == 7) ? &DDRE : &DDRB)))
#define __digitalPinToPINReg(P) \
((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PIND : (((P) == 5 || (P) == 13) ? &PINC : (((P) >= 18 && (P) <= 23)) ? &PINF : (((P) == 7) ? &PINE : &PINB)))
#define __digitalPinToBit(P) \
(((P) >= 8 && (P) <= 11) ? (P) - 4 : \
(((P) >= 18 && (P) <= 21) ? 25 - (P) : \
(((P) == 0) ? 2 : (((P) == 1) ? 3 : (((P) == 2) ? 1 : (((P) == 3) ? 0 : (((P) == 4) ? 4 : (((P) == 6) ? 7 : (((P) == 13) ? 7 : \
(((P) == 14) ? 3 : (((P) == 15) ? 1 : (((P) == 16) ? 2 : (((P) == 17) ? 0 : (((P) == 22) ? 1 : (((P) == 23) ? 0 : \
(((P) == 24) ? 4 : (((P) == 25) ? 7 : (((P) == 26) ? 4 : (((P) == 27) ? 5 : 6 )))))))))))))))))))
# endif
// --- Arduino Uno and ATmega168/328 based boards ---
#elif (defined(ARDUINO_AVR_UNO) || \
defined(ARDUINO_AVR_DUEMILANOVE) || \
defined(__AVR_ATmega8__) || \
defined(__AVR_ATmega48__) || \
defined(__AVR_ATmega48P__) || \
defined(__AVR_ATmega48PB__) || \
defined(__AVR_ATmega88P__) || \
defined(__AVR_ATmega88PB__) || \
defined(__AVR_ATmega168__) || \
defined(__AVR_ATmega168PA__) || \
defined(__AVR_ATmega168PB__) || \
defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) || \
defined(__AVR_ATmega328PB__))
#if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__)
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE)))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : (((P) >= 14 && (P) <= 19) ? &DDRC : &DDRE)))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : (((P) >= 14 && (P) <= 19) ? &PINC : &PINE)))
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (((P) >= 14 && (P) <= 19) ? (P) - 14 : (((P) >= 20 && (P) <= 21) ? (P) - 18 : (P) - 22))))
#else
#define __digitalPinToPortReg(P) \
(((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC))
#define __digitalPinToDDRReg(P) \
(((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC))
#define __digitalPinToPINReg(P) \
(((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC))
#define __digitalPinToBit(P) \
(((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
#endif
// --- Arduino Uno WiFi Rev 2, Nano Every ---
#elif defined(__AVR_ATmega4809__)
#define __digitalPinToPortReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT)
#define __digitalPinToDDRReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR)
#define __digitalPinToPINReg(P) \
(((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN)
#define __digitalPinToBit(P) \
(((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 )
// TinyCore
// https://raw.githubusercontent.com/xukangmin/TinyCore/master/avr/package/package_tinycore_index.json
// https://docs.tinycore.dev/en/latest/
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define __digitalPinToPortReg(P) ((P) <= 5 ? &VPORTB.OUT : ((P) <= 9 ? &VPORTC.OUT : ((P) <= 16 ? &VPORTA.OUT : ((P) <= 18 ? &VPORTB.OUT : &VPORTC.OUT))))
#define __digitalPinToDDRReg(P) ((P) <= 5 ? &VPORTB.DIR : ((P) <= 9 ? &VPORTC.DIR : ((P) <= 16 ? &VPORTA.DIR : ((P) <= 18 ? &VPORTB.DIR : &VPORTC.DIR))))
#define __digitalPinToPINReg(P) ((P) <= 5 ? &VPORTB.IN : ((P) <= 9 ? &VPORTC.IN : ((P) <= 16 ? &VPORTA.IN : ((P) <= 18 ? &VPORTB.IN : &VPORTC.IN))))
#define __digitalPinToBit(P) ( (P) <= 3 ? (3 - P) : ((P) <= 5 ? (P) : ((P) <= 9 ? (P - 6) : ((P) <= 16 ? ((P) - 9) : ((P) <= 18 ? ((P) - 11) : ((P) - 15))))) )
#elif defined(__AVR_ATtiny1614__)
#define __digitalPinToPortReg(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 7 ? &VPORTB.OUT : &VPORTA.OUT))
#define __digitalPinToDDRReg(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 7 ? &VPORTB.DIR : &VPORTA.DIR))
#define __digitalPinToPINReg(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 7 ? &VPORTB.IN : &VPORTA.IN))
#define __digitalPinToBit(P) ( (P) <= 3 ? (P + 4) : ((P) <= 7 ? (7 - P) : ((P) <= 10 ? (P - 7) : (P) - 11)) )
#elif defined(__AVR_ATtiny816__)
// https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1029
#define __digitalPinToPortReg(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 9 ? &VPORTB.OUT : ((P) <= 13 ? &VPORTC.OUT : ((P) <= 17 ? &VPORTA.OUT : &VPORTC.OUT))))
#define __digitalPinToDDRReg(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 9 ? &VPORTB.DIR : ((P) <= 13 ? &VPORTC.DIR : ((P) <= 17 ? &VPORTA.DIR : &VPORTC.DIR))))
#define __digitalPinToPINReg(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 9 ? &VPORTB.IN : ((P) <= 13 ? &VPORTC.IN : ((P) <= 17 ? &VPORTA.IN : &VPORTC.IN))))
#define __digitalPinToBit(P) ( (P) <= 3 ? (P + 4) : ((P) <= 9 ? (9 - P) : ((P) <= 13 ? (P - 10) : ((P) <= 16 ? (P - 13) : ((P) - 17)))) )
// --- ATtinyX5 ---
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// we have only PORTB
#define __digitalPinToPortReg(P) (&PORTB)
#define __digitalPinToDDRReg(P) (&DDRB)
#define __digitalPinToPINReg(P) (&PINB)
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14))
// --- ATtiny88 ---
#elif defined(__AVR_ATtiny88__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC)))
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC)))
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC)))
#define __digitalPinToBit(P) ( (P) <= 7 ? (P) : ((P) <= 13 ? ((P) - 8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P) - 14) : ((P) <= 18 ? ((P) - 17) : ((P) == 25 ? 7 : ((P) - 19)))))) )
# else
#define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC))))
#define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC))))
#define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC))))
#define __digitalPinToBit(P) ((P) <= 15 ? ((P) & 0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P) - 17) : ((P) == 27 ? (6) : ((P) - 23)))))
# endif
// --- ATtinyX4 + ATtinyX7 ---
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) \
|| defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO) || PIN_PA7 == 5
// Strange enumeration of pins on Digispark board and core library
#define __digitalPinToPortReg(P) (((P) <= 4) ? &PORTB : &PORTA)
#define __digitalPinToDDRReg(P) (((P) <= 4) ? &DDRB : &DDRA)
#define __digitalPinToPINReg(P) (((P) <= 4) ? &PINB : &PINA)
#define __digitalPinToBit(P) (((P) <= 2) ? (P) : (((P) == 3) ? 6 : (((P) == 4) ? 3 : (((P) == 5) ? 7 : (P) - 6 ))))
# else
// ATtinyX4: PORTA for 0 to 7, PORTB for 8 to 11
// ATtinyX7: PORTA for 0 to 7, PORTB for 8 to 15
#define __digitalPinToPortReg(P) (((P) <= 7) ? &PORTA : &PORTB)
#define __digitalPinToDDRReg(P) (((P) <= 7) ? &DDRA : &DDRB)
#define __digitalPinToPINReg(P) (((P) <= 7) ? &PINA : &PINB)
# if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__)
// https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/variants/tinyx41_cw/pins_arduino.h#L334
// Clockwise layout
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : ((P) == 11 ? (3) : 10 - (P)))
# else
#define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 )
# endif
# endif
#endif
#if !defined(digitalWriteFast)
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalWriteFast(P, V) \
do { \
if (__builtin_constant_p(P)) { \
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
} else { \
NonConstantsUsedForDigitalWriteFast(); \
} \
} while (0)
# else
#define digitalWriteFast(P, V) \
do { \
if (__builtin_constant_p(P)) { \
BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
} else { \
digitalWrite((P), (V)); \
} \
} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalWriteFast digitalWrite
# endif
#endif
#if !defined(pinModeFast)
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define pinModeFast(P, V) \
do { \
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
if (V == INPUT_PULLUP) {\
BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
} else { \
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
} \
} else { \
NonConstantsUsedForPinModeFast(); \
} \
} while (0)
# else
#define pinModeFast(P, V) \
do { \
if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
if (V == INPUT_PULLUP) {\
BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
} else { \
BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
} \
} else { \
pinMode((P), (V)); \
} \
} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define pinModeFast pinMode
# endif
#endif // !defined(pinModeFast)
#if !defined(digitalReadFast)
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPINReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
// since we have return values, it is easier to implement it by ?:
#define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : NonConstantsUsedForDigitalReadFast() )
# else
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
// since we have return values, it is easier to implement it by ?:
#define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : digitalRead((P)) )
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalReadFast digitalRead
# endif
#endif // !defined(digitalReadFast)
#if !defined(digitalToggleFast)
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPINReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalToggleFast(P) \
do { \
if (__builtin_constant_p(P)) { \
BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
} else { \
NonConstantsUsedForDigitalToggleFast(); \
} \
} while (0)
# else
#define digitalToggleFast(P) \
do { \
if (__builtin_constant_p(P)) { \
BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
} else { \
digitalWrite(P, ! digitalRead(P)); \
} \
} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P))
# endif
#endif // !defined(digitalToggleFast)
#endif // !defined(MEGATINYCORE)
#endif //__digitalWriteFast_h_
================================================
FILE: src/irmp.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmp.h
*
* Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_H_
#define _IRMP_H_
#if !defined(IRMP_USE_AS_LIB)
# define IRMPCONFIG_STAGE1_H
# include "irmpconfig.h"
# undef IRMPCONFIG_STAGE1_H
#endif
#include "irmpsystem.h"
#if !defined(IRMP_USE_AS_LIB)
# define IRMPCONFIG_STAGE2_H
# include "irmpconfig.h"
# undef IRMPCONFIG_STAGE2_H
#endif
#if defined(ARDUINO)
# include "irmpArduinoExt.h"
#elif defined (__AVR_XMEGA__)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_PORT_PRE CONCAT(PORT, IRMP_PORT_LETTER)
# define IRMP_DDR_PRE CONCAT(PORT, IRMP_PORT_LETTER)
# define IRMP_PIN_PRE CONCAT(PORT, IRMP_PORT_LETTER)
# define IRMP_PORT IRMP_PORT_PRE.OUT
# define IRMP_DDR IRMP_DDR_PRE.DIR
# define IRMP_PIN IRMP_PIN_PRE.IN
# define IRMP_BIT IRMP_BIT_NUMBER
# define input(x) ((x) & (1 << IRMP_BIT))
#elif defined (ATMEL_AVR)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_PORT CONCAT(PORT, IRMP_PORT_LETTER)
# define IRMP_DDR CONCAT(DDR, IRMP_PORT_LETTER)
# define IRMP_PIN CONCAT(PIN, IRMP_PORT_LETTER)
# define IRMP_BIT IRMP_BIT_NUMBER
# define input(x) ((x) & (1 << IRMP_BIT))
#elif defined (PIC_C18) || defined (PIC_CCS) || defined(PIC_XC32)
# define input(x) (x)
#elif defined (ARM_STM32)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_PORT CONCAT(GPIO, IRMP_PORT_LETTER)
# if defined (ARM_STM32L1XX)
# define IRMP_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRMP_PORT_LETTER)
# elif defined (ARM_STM32F10X)
# define IRMP_PORT_RCC CONCAT(RCC_APB2Periph_GPIO, IRMP_PORT_LETTER)
# elif defined (ARM_STM32F30X)
# define IRMP_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRMP_PORT_LETTER)
# elif defined (ARM_STM32F4XX)
# define IRMP_PORT_RCC CONCAT(RCC_AHB1Periph_GPIO, IRMP_PORT_LETTER)
# endif
# define IRMP_BIT CONCAT(GPIO_Pin_, IRMP_BIT_NUMBER)
# define IRMP_PIN IRMP_PORT // for use with input(x) below
# define input(x) (GPIO_ReadInputDataBit(x, IRMP_BIT))
# if !defined(USE_STDPERIPH_DRIVER)
# warning The STM32 port of IRMP uses the ST standard peripheral drivers which are not enabled in your build configuration.
# endif
#elif defined (ARM_STM32_OPENCM3)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_PORT CONCAT(GPIO, IRMP_PORT_LETTER)
# define IRMP_PORT_RCC CONCAT(RCC_GPIO, IRMP_PORT_LETTER)
# define IRMP_BIT CONCAT(GPIO, IRMP_BIT_NUMBER)
# define IRMP_PIN IRMP_PORT // for use with input(x) below
# define input(x) (gpio_get(x, IRMP_BIT))
#elif defined (ARM_STM32_HAL)
# define IRMP_BIT IRMP_BIT_NUMBER
# define IRMP_PIN IRMP_BIT_NUMBER // for use with input(x) below
# define input(x) HAL_GPIO_ReadPin(IRMP_PORT_LETTER, x)
#elif defined (STELLARIS_ARM_CORTEX_M4)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_PORT_PERIPH CONCAT(SYSCTL_PERIPH_GPIO, IRMP_PORT_LETTER)
# define IRMP_PORT_BASE CONCAT(GPIO_PORT, CONCAT(IRMP_PORT_LETTER, _BASE))
# define IRMP_PORT_PIN CONCAT(GPIO_PIN_, IRMP_BIT_NUMBER)
# define IRMP_PIN IRMP_PORT_PIN
# define input(x) ((uint8_t)(ROM_GPIOPinRead(IRMP_PORT_BASE, IRMP_PORT_PIN)))
# define sei() IntMasterEnable()
#elif defined(__SDCC_stm8)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRMP_GPIO_STRUCT CONCAT(GPIO, IRMP_PORT_LETTER)
# define IRMP_BIT IRMP_BIT_NUMBER
# define IRMP_PIN IRMP_GPIO_STRUCT->IDR
# define input(x) ((x) & (1 << IRMP_BIT))
#elif defined (PICO_RP2040)
# define IRMP_BIT IRMP_BIT_NUMBER
# define IRMP_PIN IRMP_BIT_NUMBER // for use with input(x) below
# define input(x) (gpio_get(x))
#elif defined (TEENSY_ARM_CORTEX_M4)
# define input(x) ((uint8_t)(digitalReadFast(x)))
#elif defined (__MBED__)
# define IRMP_BIT gpioIRin
# define input(x) (gpio_read (&x))
#elif defined(__xtensa__)
# define IRMP_BIT IRMP_BIT_NUMBER
# define input(x) GPIO_INPUT_GET(IRMP_BIT_NUMBER)
#elif defined(_CHIBIOS_HAL_)
# define input(x) palReadLine(x)
#endif
#if IRMP_USE_IDLE_CALL == 1
void irmp_idle(void); // the user has to provide an implementation of the irmp_idle() function and link it
#endif
#if IRMP_USE_COMPLETE_CALLBACK == 1
void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void));
#endif
#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1
# undef IRMP_SUPPORT_MATSUSHITA_PROTOCOL
# define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1
#endif
#if IRMP_32_BIT == 0 && IRMP_SUPPORT_MERLIN_PROTOCOL == 1
# undef IRMP_SUPPORT_MERLIN_PROTOCOL
# warning MERLIN protocol disabled, IRMP_32_BIT=1 needed
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_RUWIDO_PROTOCOL == 1
# warning DENON protocol conflicts wih RUWIDO, please enable only one of both protocols
# warning RUWIDO protocol disabled
# undef IRMP_SUPPORT_RUWIDO_PROTOCOL
# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 && IRMP_SUPPORT_PANASONIC_PROTOCOL == 1
# warning KASEIKYO protocol conflicts wih PANASONIC, please enable only one of both protocols
# warning PANASONIC protocol disabled
# undef IRMP_SUPPORT_PANASONIC_PROTOCOL
# define IRMP_SUPPORT_PANASONIC_PROTOCOL 0
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_ACP24_PROTOCOL == 1
# warning DENON protocol conflicts wih ACP24, please enable only one of both protocols
# warning ACP24 protocol disabled
# undef IRMP_SUPPORT_ACP24_PROTOCOL
# define IRMP_SUPPORT_ACP24_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1 && IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
# warning RC6 protocol conflicts wih ROOMBA, please enable only one of both protocols
# warning ROOMBA protocol disabled
# undef IRMP_SUPPORT_ROOMBA_PROTOCOL
# define IRMP_SUPPORT_ROOMBA_PROTOCOL 0
#endif
#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 && IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
# warning PANASONIC protocol conflicts wih MITSU_HEAVY, please enable only one of both protocols
# warning MITSU_HEAVY protocol disabled
# undef IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
# define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 && IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
# warning KASEIKYO protocol conflicts wih MITSU_HEAVY, please enable only one of both protocols
# warning MITSU_HEAVY protocol disabled
# undef IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
# define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1
# warning RC5 protocol conflicts wih ORTEK, please enable only one of both protocols
# warning ORTEK protocol disabled
# undef IRMP_SUPPORT_ORTEK_PROTOCOL
# define IRMP_SUPPORT_ORTEK_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_S100_PROTOCOL == 1
# warning RC5 protocol conflicts wih S100, please enable only one of both protocols
# warning S100 protocol disabled
# undef IRMP_SUPPORT_S100_PROTOCOL
# define IRMP_SUPPORT_S100_PROTOCOL 0
#endif
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 && IRMP_SUPPORT_FAN_PROTOCOL == 1
# warning NUBERT protocol conflicts wih FAN, please enable only one of both protocols
# warning FAN protocol disabled
# undef IRMP_SUPPORT_FAN_PROTOCOL
# define IRMP_SUPPORT_FAN_PROTOCOL 0
#endif
#if IRMP_SUPPORT_FDC_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1
# warning FDC protocol conflicts wih ORTEK, please enable only one of both protocols
# warning ORTEK protocol disabled
# undef IRMP_SUPPORT_ORTEK_PROTOCOL
# define IRMP_SUPPORT_ORTEK_PROTOCOL 0
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 && IRMP_SUPPORT_NETBOX_PROTOCOL == 1
# warning ORTEK protocol conflicts wih NETBOX, please enable only one of both protocols
# warning NETBOX protocol disabled
# undef IRMP_SUPPORT_NETBOX_PROTOCOL
# define IRMP_SUPPORT_NETBOX_PROTOCOL 0
#endif
#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1
# warning GRUNDIG protocol conflicts wih RCII, please enable only one of both protocols
# warning RCII protocol disabled
# undef IRMP_SUPPORT_RCII_PROTOCOL
# define IRMP_SUPPORT_RCII_PROTOCOL 0
#endif
#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1
# warning NOKIA protocol conflicts wih RCII, please enable only one of both protocols
# warning RCII protocol disabled
# undef IRMP_SUPPORT_RCII_PROTOCOL
# define IRMP_SUPPORT_RCII_PROTOCOL 0
#endif
#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000)
# undef IRMP_SUPPORT_SIEMENS_PROTOCOL
# define IRMP_SUPPORT_SIEMENS_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, RUWIDO protocol disabled (should be at least 15000)
# undef IRMP_SUPPORT_RUWIDO_PROTOCOL
# define IRMP_SUPPORT_RUWIDO_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000)
# undef IRMP_SUPPORT_RECS80_PROTOCOL
# define IRMP_SUPPORT_RECS80_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000)
# undef IRMP_SUPPORT_RECS80EXT_PROTOCOL
# define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0
#endif
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 19000
# warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 19000)
# undef IRMP_SUPPORT_LEGO_PROTOCOL
# define IRMP_SUPPORT_LEGO_PROTOCOL 0
#endif
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 0
# warning SAMSUNG48 protocol needs also SAMSUNG protocol, SAMSUNG protocol enabled
# undef IRMP_SUPPORT_SAMSUNG_PROTOCOL
# define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1
#endif
#if IRMP_SUPPORT_JVC_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0
# warning JVC protocol needs also NEC protocol, NEC protocol enabled
# undef IRMP_SUPPORT_NEC_PROTOCOL
# define IRMP_SUPPORT_NEC_PROTOCOL 1
#endif
#if IRMP_SUPPORT_NEC16_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0
# warning NEC16 protocol needs also NEC protocol, NEC protocol enabled
# undef IRMP_SUPPORT_NEC_PROTOCOL
# define IRMP_SUPPORT_NEC_PROTOCOL 1
#endif
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0
# warning NEC42 protocol needs also NEC protocol, NEC protocol enabled
# undef IRMP_SUPPORT_NEC_PROTOCOL
# define IRMP_SUPPORT_NEC_PROTOCOL 1
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0
# warning LGAIR protocol needs also NEC protocol, NEC protocol enabled
# undef IRMP_SUPPORT_NEC_PROTOCOL
# define IRMP_SUPPORT_NEC_PROTOCOL 1
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0
# warning MELINERA protocol needs also NEC protocol, NEC protocol enabled
# undef IRMP_SUPPORT_NEC_PROTOCOL
# define IRMP_SUPPORT_NEC_PROTOCOL 1
#endif
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1 && F_INTERRUPTS < 19000
# warning F_INTERRUPTS too low, RCMM protocol disabled (should be at least 19000)
# undef IRMP_SUPPORT_RCMM_PROTOCOL
# define IRMP_SUPPORT_RCMM_PROTOCOL 0
#endif
#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 && F_INTERRUPTS > 17000 && __SIZEOF_INT__ < 4
# warning F_INTERRUPTS too high, PENTAX protocol disabled (should be max 17000)
# undef IRMP_SUPPORT_PENTAX_PROTOCOL
# define IRMP_SUPPORT_PENTAX_PROTOCOL 0
#endif
#if IRMP_SUPPORT_GREE_PROTOCOL == 1 && F_INTERRUPTS > 17000 && __SIZEOF_INT__ < 4
# warning F_INTERRUPTS too high, GREE protocol disabled (should be max 17000)
# undef IRMP_SUPPORT_GREE_PROTOCOL
# define IRMP_SUPPORT_GREE_PROTOCOL 0
#endif
#if F_INTERRUPTS > 20000
# warning F_INTERRUPTS too high (should be not greater than 20000)
#endif
#include "irmpprotocols.h"
#define IRMP_FLAG_NEW 0x00
#define IRMP_FLAG_REPETITION 0x01
#define IRMP_FLAG_RELEASE 0x02 // see IRMP_ENABLE_RELEASE_DETECTION in irmpconfig.h
#ifdef __cplusplus
extern "C"
{
#endif
extern void irmp_init (void);
#ifdef __cplusplus
extern bool irmp_get_data (IRMP_DATA *);
extern bool irmp_ISR (void);
#else
extern uint_fast8_t irmp_get_data (IRMP_DATA *);
extern uint_fast8_t irmp_ISR (void);
#endif
#if IRMP_AUTODETECT_REPEATRATE
extern volatile uint_fast8_t delta, min_delta, keep_same_key, timeout, upper_border;
extern volatile uint_fast16_t tmp_delta;
extern volatile uint32_t pass_on_delta_detection;
#endif
#if IRMP_PROTOCOL_NAMES == 1
extern const char * const irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM;
#endif
#if IRMP_USE_CALLBACK == 1
extern void irmp_set_callback_ptr (void (*cb)(uint_fast8_t));
#endif // IRMP_USE_CALLBACK == 1
#ifdef __cplusplus
}
#endif
#endif /* _IRMP_H_ */
================================================
FILE: src/irmp.hpp
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmp.hpp - infrared multi-protocol decoder, supports several remote control protocols
*
* Copyright (c) 2009-2019 Frank Meyer - frank(at)fli4l.de
* 2020 Arduino porting by Armin Joachimsmeyer
*
* Supported AVR mikrocontrollers:
*
* ATtiny87, ATtiny167
* ATtiny45, ATtiny85
* ATtiny44, ATtiny84
* ATmega8, ATmega16, ATmega32
* ATmega162
* ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284, ATmega1284P
* ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#include "irmp.h"
#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRMP_SUPPORT_NOKIA_PROTOCOL == 1 || IRMP_SUPPORT_IR60_PROTOCOL == 1
# define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 1
#else
# define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 0
#endif
#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 || IRMP_SUPPORT_RUWIDO_PROTOCOL == 1
# define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 1
#else
# define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 0
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || \
IRMP_SUPPORT_RCII_PROTOCOL == 1 || \
IRMP_SUPPORT_S100_PROTOCOL == 1 || \
IRMP_SUPPORT_RC6_PROTOCOL == 1 || \
IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 || \
IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 || \
IRMP_SUPPORT_IR60_PROTOCOL == 1 || \
IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 || \
IRMP_SUPPORT_MERLIN_PROTOCOL == 1 || \
IRMP_SUPPORT_ORTEK_PROTOCOL == 1
# define IRMP_SUPPORT_MANCHESTER 1
#else
# define IRMP_SUPPORT_MANCHESTER 0
#endif
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1
# define IRMP_SUPPORT_SERIAL 1
#else
# define IRMP_SUPPORT_SERIAL 0
#endif
#define IRMP_KEY_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * 150.0e-3 + 0.5) // autodetect key repetition within 150 msec
#define MIN_TOLERANCE_00 1.0 // -0%
#define MAX_TOLERANCE_00 1.0 // +0%
#define MIN_TOLERANCE_02 0.98 // -2%
#define MAX_TOLERANCE_02 1.02 // +2%
#define MIN_TOLERANCE_03 0.97 // -3%
#define MAX_TOLERANCE_03 1.03 // +3%
#define MIN_TOLERANCE_05 0.95 // -5%
#define MAX_TOLERANCE_05 1.05 // +5%
#define MIN_TOLERANCE_10 0.9 // -10%
#define MAX_TOLERANCE_10 1.1 // +10%
#define MIN_TOLERANCE_15 0.85 // -15%
#define MAX_TOLERANCE_15 1.15 // +15%
#define MIN_TOLERANCE_20 0.8 // -20%
#define MAX_TOLERANCE_20 1.2 // +20%
#define MIN_TOLERANCE_25 0.75 // -25%
#define MAX_TOLERANCE_25 1.25 // +25%
#define MIN_TOLERANCE_30 0.7 // -30%
#define MAX_TOLERANCE_30 1.3 // +30%
#define MIN_TOLERANCE_40 0.6 // -40%
#define MAX_TOLERANCE_40 1.4 // +40%
#define MIN_TOLERANCE_50 0.5 // -50%
#define MAX_TOLERANCE_50 1.5 // +50%
#define MIN_TOLERANCE_60 0.4 // -60%
#define MAX_TOLERANCE_60 1.6 // +60%
#define MIN_TOLERANCE_70 0.3 // -70%
#define MAX_TOLERANCE_70 1.7 // +70%
#define SIRCS_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SIRCS_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIRCS_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#if IRMP_SUPPORT_NETBOX_PROTOCOL // only 5% to avoid conflict with NETBOX:
# define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5))
#else // only 5% + 1 to avoid conflict with RC6:
# define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#endif
#define SIRCS_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SIRCS_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIRCS_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SIRCS_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIRCS_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SIRCS_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define NEC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define NEC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define NEC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define NEC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define NEC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define NEC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define NEC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
// autodetect nec repetition frame within 50 msec:
// NEC seems to send the first repetition frame after 40ms, further repetition frames after 100 ms
#if 0
#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5)
#else
#define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5)
#endif
#define MELINERA_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MELINERA_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define MELINERA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MELINERA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define MELINERA_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MELINERA_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define MELINERA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MELINERA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNG_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SAMSUNG_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SAMSUNG_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SAMSUNG_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SAMSUNG_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNG_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNG_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNG_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNG_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNG_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNGAH_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SAMSUNGAH_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SAMSUNGAH_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define SAMSUNGAH_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SAMSUNGAH_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNGAH_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNGAH_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNGAH_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define SAMSUNGAH_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define SAMSUNGAH_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define MATSUSHITA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define MATSUSHITA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define MATSUSHITA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define MATSUSHITA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define MATSUSHITA_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define MATSUSHITA_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define MATSUSHITA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define MATSUSHITA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define MATSUSHITA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define MATSUSHITA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define KASEIKYO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define KASEIKYO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define KASEIKYO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define KASEIKYO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define KASEIKYO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define KASEIKYO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define MITSU_HEAVY_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define MITSU_HEAVY_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define MITSU_HEAVY_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define MITSU_HEAVY_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define MITSU_HEAVY_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define MITSU_HEAVY_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define MITSU_HEAVY_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define MITSU_HEAVY_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define PANASONIC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define PANASONIC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define PANASONIC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define PANASONIC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define PANASONIC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define PANASONIC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define PANASONIC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PANASONIC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define PANASONIC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PANASONIC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define VINCENT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define VINCENT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define VINCENT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define VINCENT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define VINCENT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define VINCENT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define VINCENT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define VINCENT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define VINCENT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define VINCENT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RECS80_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define RECS80_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RECS80_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RECS80_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define RECS80_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RECS80_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RECS80_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#if (0) // IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with RC5, so keep tolerance for RC5 minimal here:
// start pause is well separated, so overlap in start pulse does not disturb, but reducing tolerance leads to worse RC5 recognition
#define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#else
#define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#endif
#define RC5_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC5_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RCII_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCII_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCII_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCII_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCII_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCII_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCII_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RCII_BIT_LEN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME))
#define RCII_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with S100, so keep tolerance for S100 minimal here:
#define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#else
#define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#endif
#define S100_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define S100_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define DENON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define DENON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define DENON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define DENON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
// RUWIDO (see t-home-mediareceiver-15kHz.txt) conflicts here with DENON
#define DENON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define DENON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define DENON_AUTO_REPETITION_PAUSE_LEN ((uint_fast16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define THOMSON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define THOMSON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define THOMSON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define THOMSON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define THOMSON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define THOMSON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RC6_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC6_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RC6_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC6_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RC6_TOGGLE_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC6_TOGGLE_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RC6_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC6_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_60 + 0.5) + 1) // pulses: 300 - 800
#define RC6_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RC6_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pauses: 300 - 600
#define RECS80EXT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define RECS80EXT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RECS80EXT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80EXT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RECS80EXT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define RECS80EXT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RECS80EXT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80EXT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RECS80EXT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RECS80EXT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define NUBERT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NUBERT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NUBERT_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NUBERT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NUBERT_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NUBERT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NUBERT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define FAN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FAN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SPEAKER_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define SPEAKER_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX ((PAUSE_LEN)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) // value must be below IRMP_TIMEOUT
#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_R_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_R_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define IR60_TIMEOUT_LEN ((uint_fast8_t)(F_INTERRUPTS * IR60_TIMEOUT_TIME * 0.5))
#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define GRUNDIG_NOKIA_IR60_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define GRUNDIG_NOKIA_IR60_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1)
#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 0)
#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1)
#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1)
#define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1)
#define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define FDC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) // 5%: avoid conflict with NETBOX
#define FDC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5))
#define FDC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define FDC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5))
#define FDC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define FDC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1)
#define FDC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define FDC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#if 0
#define FDC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) // could be negative: 255
#else
#define FDC_0_PAUSE_LEN_MIN (1) // simply use 1
#endif
#define FDC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RCCAR_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RCCAR_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RCCAR_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RCCAR_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RCCAR_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define RCCAR_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RCCAR_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RCCAR_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MAX_TOLERANCE_25 + 0.5) + 1)
#define RCCAR_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MIN_TOLERANCE_25 + 0.5) - 1)
#define RCCAR_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define JVC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define JVC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define JVC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MIN_TOLERANCE_40 + 0.5) - 1) // HACK!
#define JVC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MAX_TOLERANCE_70 + 0.5) - 1) // HACK!
#define JVC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define JVC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define JVC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define JVC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define JVC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define JVC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
// autodetect JVC repetition frame within 50 msec:
#define JVC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5)
#define NIKON_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_START_BIT_PAUSE_LEN_MIN ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_START_BIT_PAUSE_LEN_MAX ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define NIKON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define NIKON_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5)
#define KATHREIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define KATHREIN_SYNC_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define KATHREIN_SYNC_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define NETBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define NETBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define NETBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define NETBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define NETBOX_PULSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME))
#define NETBOX_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME))
#define NETBOX_PULSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME / 4))
#define NETBOX_PAUSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME / 4))
#define LEGO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define LEGO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define LEGO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define LEGO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define LEGO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define LEGO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define LEGO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MIN_TOLERANCE_25 + 0.5) - 1)
#define LEGO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1)
#define LEGO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1)
#define LEGO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define IRMP16_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define IRMP16_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define IRMP16_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define IRMP16_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define IRMP16_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define IRMP16_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define IRMP16_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define IRMP16_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define IRMP16_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define IRMP16_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define GREE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define GREE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define GREE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define GREE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define GREE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define GREE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define GREE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define GREE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define GREE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define GREE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define BOSE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define BOSE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define BOSE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define BOSE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define BOSE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define BOSE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define BOSE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define BOSE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define BOSE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define BOSE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define BOSE_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5)
#define A1TVBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define A1TVBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define A1TVBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define A1TVBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_00 + 0.5) + 1)
#define A1TVBOX_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define A1TVBOX_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define A1TVBOX_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 0)
#define A1TVBOX_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define MERLIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define MERLIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define MERLIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define MERLIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define MERLIN_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MERLIN_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define MERLIN_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define MERLIN_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define ORTEK_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ORTEK_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define ORTEK_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ORTEK_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define ORTEK_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ORTEK_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define ORTEK_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ORTEK_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define TELEFUNKEN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define TELEFUNKEN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define TELEFUNKEN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MIN_TOLERANCE_10 + 0.5) - 1)
#define TELEFUNKEN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MAX_TOLERANCE_10 + 0.5) - 1)
#define TELEFUNKEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define TELEFUNKEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define TELEFUNKEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define TELEFUNKEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define TELEFUNKEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define TELEFUNKEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
// autodetect TELEFUNKEN repetition frame within 50 msec:
// #define TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5)
#define ROOMBA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ROOMBA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define ROOMBA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define ROOMBA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define ROOMBA_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME + 0.5))
#define ROOMBA_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define ROOMBA_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define ROOMBA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define ROOMBA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define ROOMBA_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME))
#define ROOMBA_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define ROOMBA_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define ROOMBA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define ROOMBA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define RCMM32_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_BIT_00_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_BIT_00_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_BIT_01_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_BIT_01_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_BIT_10_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_BIT_10_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RCMM32_BIT_11_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RCMM32_BIT_11_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define PENTAX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define PENTAX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define PENTAX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define PENTAX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define PENTAX_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME + 0.5))
#define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define PENTAX_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PENTAX_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define PENTAX_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME))
#define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define PENTAX_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define PENTAX_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define ACP24_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1)
#define ACP24_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1)
#define ACP24_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1)
#define ACP24_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1)
#define ACP24_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1)
#define ACP24_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1)
#define ACP24_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1)
#define ACP24_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1)
#define ACP24_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1)
#define ACP24_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1)
#define METZ_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define METZ_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define METZ_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define METZ_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define METZ_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define METZ_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define METZ_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define METZ_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define METZ_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1)
#define METZ_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1)
#define METZ_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * METZ_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5)
#define RF_GEN24_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME + 0.5))
#define RF_GEN24_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RF_GEN24_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define RF_GEN24_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RF_GEN24_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define RF_GEN24_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME))
#define RF_GEN24_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RF_GEN24_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define RF_GEN24_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1)
#define RF_GEN24_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1)
#define RF_X10_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RF_X10_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RF_X10_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RF_X10_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RF_X10_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME + 0.5))
#define RF_X10_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_X10_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_X10_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_X10_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_X10_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME))
#define RF_X10_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_X10_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_X10_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_X10_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_MEDION_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RF_MEDION_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RF_MEDION_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1)
#define RF_MEDION_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1)
#define RF_MEDION_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME + 0.5))
#define RF_MEDION_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_MEDION_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_MEDION_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_MEDION_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_MEDION_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME))
#define RF_MEDION_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_MEDION_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define RF_MEDION_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1)
#define RF_MEDION_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1)
#define AUTO_FRAME_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * AUTO_FRAME_REPETITION_TIME + 0.5) // use uint_fast16_t!
#define STOP_BIT_PAUSE_TIME_MIN 3000.0e-6 // minimum stop bit pause time: 3.0 msec
#define STOP_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * STOP_BIT_PAUSE_TIME_MIN + 0.5) + 1) // minimum stop bit pause len
// XC8 Compiler does not support variadic macros
#if defined(ANALYZE)
# define ANALYZE_PUTCHAR(a) { if (! silent) { putchar (a); } }
# define ANALYZE_ONLY_NORMAL_PUTCHAR(a) { if (! silent && !verbose) { putchar (a); } }
// # define ANALYZE_PRINTF(...) { if (verbose) { printf (__VA_ARGS__); } }
# define ANALYZE_PRINTF1(a) { if (verbose) { printf (a); } }
# define ANALYZE_PRINTF2(a,b) { if (verbose) { printf (a,b); } }
# define ANALYZE_PRINTF3(a,b,c) { if (verbose) { printf (a,b,c); } }
# define ANALYZE_PRINTF4(a,b,c,d) { if (verbose) { printf (a,b,c,d); } }
# define ANALYZE_PRINTF5(a,b,c,d,e) { if (verbose) { printf (a,b,c,d,e); } }
# define ANALYZE_PRINTF6(a,b,c,d,e,f) { if (verbose) { printf (a,b,c,d,e,f); } }
# define ANALYZE_PRINTF7(a,b,c,d,e,f,g) { if (verbose) { printf (a,b,c,d,e,f,g); } }
# define ANALYZE_PRINTF8(a,b,c,d,e,f,g,h) { if (verbose) { printf (a,b,c,d,e,f,g,h); } }
# define ANALYZE_PRINTF9(a,b,c,d,e,f,g,h,i) { if (verbose) { printf (a,b,c,d,e,f,g,h,i); } }
//# define ANALYZE_ONLY_NORMAL_PRINTF(...) { if (! silent && !verbose) { printf (__VA_ARGS__); } }
# define ANALYZE_ONLY_NORMAL_PRINTF1(a) { if (! silent && !verbose) { printf (a); } }
# define ANALYZE_NEWLINE() { if (verbose) { putchar ('\n'); } }
static int silent;
static int time_counter;
static int verbose;
#else
# define ANALYZE_PUTCHAR(a)
# define ANALYZE_ONLY_NORMAL_PUTCHAR(a)
// # define ANALYZE_PRINTF(...)
# define ANALYZE_PRINTF1(a)
# define ANALYZE_PRINTF2(a,b)
# define ANALYZE_PRINTF3(a,b,c)
# define ANALYZE_PRINTF4(a,b,c,d)
# define ANALYZE_PRINTF5(a,b,c,d,e)
# define ANALYZE_PRINTF6(a,b,c,d,e,f)
# define ANALYZE_PRINTF7(a,b,c,d,e,f,g)
# define ANALYZE_PRINTF8(a,b,c,d,e,f,g,h)
# define ANALYZE_PRINTF9(a,b,c,d,e,f,g,h,i)
//# define ANALYZE_ONLY_NORMAL_PRINTF(...)
# define ANALYZE_ONLY_NORMAL_PRINTF1(a)
# define ANALYZE_NEWLINE()
#endif
#if IRMP_USE_CALLBACK == 1
static void (*irmp_callback_ptr) (uint_fast8_t);
#endif // IRMP_USE_CALLBACK == 1
#if IRMP_USE_COMPLETE_CALLBACK == 1
static void (*irmp_complete_callback_function)(void);
void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void)) {
irmp_complete_callback_function = aCompleteCallbackFunction;
}
#endif // IRMP_USE_COMPLETE_CALLBACK == 1
#define PARITY_CHECK_OK 1
#define PARITY_CHECK_FAILED 0
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocol names
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1
#include "irmpprotocols.hpp" // include protocol strings and array of strings
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Logging
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if IRMP_LOGGING == 1 // logging via UART
#if defined(ARM_STM32F4XX)
# define STM32_GPIO_CLOCK RCC_AHB1Periph_GPIOA // UART2 on PA2
# define STM32_UART_CLOCK RCC_APB1Periph_USART2
# define STM32_GPIO_PORT GPIOA
# define STM32_GPIO_PIN GPIO_Pin_2
# define STM32_GPIO_SOURCE GPIO_PinSource2
# define STM32_UART_AF GPIO_AF_USART2
# define STM32_UART_COM USART2
# define STM32_UART_BAUD 115200 // 115200 Baud
# include "stm32f4xx_usart.h"
#elif defined(ARM_STM32F10X) || defined(ARM_STM32F30X)
# define STM32_UART_COM USART3 // UART3 on PB10
#elif defined(ARDUINO) // Arduino Serial implementation
# include "HardwareSerial.h"
#elif defined(_CHIBIOS_HAL_) // ChibiOS HAL
# if IRMP_EXT_LOGGING == 1
# error IRMP_EXT_LOGGING not implemented for ChibiOS HAL, use regular logging instead
# endif
#else
# if IRMP_EXT_LOGGING == 1 // use external logging
# include "irmpextlog.h"
# else // normal UART log (IRMP_EXT_LOGGING == 0)
# define BAUD 9600L
# if !defined(UNIX_OR_WINDOWS)
# include
# endif
#if defined(UBRR)0H
#define UART0_UBRRH UBRR0H
#define UART0_UBRRL UBRR0L
#define UART0_UCSRA UCSR0A
#define UART0_UCSRB UCSR0B
#define UART0_UCSRC UCSR0C
#define UART0_UDRE_BIT_VALUE (1< ENDBITS) // if high received then look at log-stop condition
{ // if stop condition is true, output on uart
uint_fast8_t i8;
uint_fast16_t i;
uint_fast16_t j;
uint_fast8_t v = '1';
uint_fast16_t d;
for (i8 = 0; i8 < STARTCYCLES; i8++)
{
irmp_uart_putc ('0'); // the ignored starting zeros
}
for (i = 0; i < buf_idx; i++)
{
d = buf[i];
if (d == 0xff)
{
i++;
d = buf[i];
i++;
d |= ((uint_fast16_t) buf[i] << 8);
}
for (j = 0; j < d; j++)
{
irmp_uart_putc (v);
}
v = (v == '1') ? '0' : '1';
}
for (i8 = 0; i8 < 20; i8++)
{
irmp_uart_putc ('1');
}
irmp_uart_putc ('\n');
buf_idx = 0;
last_val = 1;
cnt = 0;
}
}
else if (buf_idx < DATALEN - 3)
{
if (cnt >= 0xff)
{
buf[buf_idx++] = 0xff;
buf[buf_idx++] = (cnt & 0xff);
buf[buf_idx] = (cnt >> 8);
}
else
{
buf[buf_idx] = cnt;
}
buf_idx++;
cnt = 1;
last_val = val;
}
}
}
}
#else
#define irmp_log(val)
#endif //IRMP_LOGGING
typedef struct
{
uint_fast8_t protocol; // ir protocol
uint_fast8_t pulse_1_len_min; // minimum length of pulse with bit value 1
uint_fast8_t pulse_1_len_max; // maximum length of pulse with bit value 1
uint_fast8_t pause_1_len_min; // minimum length of pause with bit value 1
uint_fast8_t pause_1_len_max; // maximum length of pause with bit value 1
uint_fast8_t pulse_0_len_min; // minimum length of pulse with bit value 0
uint_fast8_t pulse_0_len_max; // maximum length of pulse with bit value 0
uint_fast8_t pause_0_len_min; // minimum length of pause with bit value 0
uint_fast8_t pause_0_len_max; // maximum length of pause with bit value 0
uint_fast8_t address_offset; // address offset
uint_fast8_t address_end; // end of address
uint_fast8_t command_offset; // command offset
uint_fast8_t command_end; // end of command
uint_fast8_t complete_len; // complete length of frame
uint_fast8_t stop_bit; // flag: frame has stop bit
uint_fast8_t lsb_first; // flag: LSB first
uint_fast8_t flags; // some flags
} IRMP_PARAMETER;
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER sircs_param =
{
IRMP_SIRCS_PROTOCOL, // protocol: ir protocol
SIRCS_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
SIRCS_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
SIRCS_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
SIRCS_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
SIRCS_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
SIRCS_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
SIRCS_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
SIRCS_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
SIRCS_ADDRESS_OFFSET, // address_offset: address offset
SIRCS_ADDRESS_OFFSET + SIRCS_ADDRESS_LEN, // address_end: end of address
SIRCS_COMMAND_OFFSET, // command_offset: command offset
SIRCS_COMMAND_OFFSET + SIRCS_COMMAND_LEN, // command_end: end of command
SIRCS_COMPLETE_DATA_LEN, // complete_len: complete length of frame
SIRCS_STOP_BIT, // stop_bit: flag: frame has stop bit
SIRCS_LSB, // lsb_first: flag: LSB first
SIRCS_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER nec_param =
{
IRMP_NEC_PROTOCOL, // protocol: ir protocol
NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
NEC_ADDRESS_OFFSET, // address_offset: address offset
NEC_ADDRESS_OFFSET + NEC_ADDRESS_LEN, // address_end: end of address
NEC_COMMAND_OFFSET, // command_offset: command offset
NEC_COMMAND_OFFSET + NEC_COMMAND_LEN, // command_end: end of command
NEC_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NEC_STOP_BIT, // stop_bit: flag: frame has stop bit
NEC_LSB, // lsb_first: flag: LSB first
NEC_FLAGS // flags: some flags
};
static const PROGMEM IRMP_PARAMETER nec_rep_param =
{
IRMP_NEC_PROTOCOL, // protocol: ir protocol
NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
0, // address_offset: address offset
0, // address_end: end of address
0, // command_offset: command offset
0, // command_end: end of command
0, // complete_len: complete length of frame
NEC_STOP_BIT, // stop_bit: flag: frame has stop bit
NEC_LSB, // lsb_first: flag: LSB first
NEC_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER nec42_param =
{
IRMP_NEC42_PROTOCOL, // protocol: ir protocol
NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
NEC42_ADDRESS_OFFSET, // address_offset: address offset
NEC42_ADDRESS_OFFSET + NEC42_ADDRESS_LEN, // address_end: end of address
NEC42_COMMAND_OFFSET, // command_offset: command offset
NEC42_COMMAND_OFFSET + NEC42_COMMAND_LEN, // command_end: end of command
NEC42_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NEC_STOP_BIT, // stop_bit: flag: frame has stop bit
NEC_LSB, // lsb_first: flag: LSB first
NEC_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
#if 0 // not needed, switching from NEC
static const PROGMEM IRMP_PARAMETER lgair_param =
{
IRMP_LGAIR_PROTOCOL, // protocol: ir protocol
NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
LGAIR_ADDRESS_OFFSET, // address_offset: address offset
LGAIR_ADDRESS_OFFSET + LGAIR_ADDRESS_LEN, // address_end: end of address
LGAIR_COMMAND_OFFSET, // command_offset: command offset
LGAIR_COMMAND_OFFSET + LGAIR_COMMAND_LEN, // command_end: end of command
LGAIR_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NEC_STOP_BIT, // stop_bit: flag: frame has stop bit
NEC_LSB, // lsb_first: flag: LSB first
NEC_FLAGS // flags: some flags
};
#endif // 0 not needed, switching from NEC
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER samsung_param =
{
IRMP_SAMSUNG_PROTOCOL, // protocol: ir protocol
SAMSUNG_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
SAMSUNG_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
SAMSUNG_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
SAMSUNG_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
SAMSUNG_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
SAMSUNG_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
SAMSUNG_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
SAMSUNG_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
SAMSUNG_ADDRESS_OFFSET, // address_offset: address offset
SAMSUNG_ADDRESS_OFFSET + SAMSUNG_ADDRESS_LEN, // address_end: end of address
SAMSUNG_COMMAND_OFFSET, // command_offset: command offset
SAMSUNG_COMMAND_OFFSET + SAMSUNG_COMMAND_LEN, // command_end: end of command
SAMSUNG_COMPLETE_DATA_LEN, // complete_len: complete length of frame
SAMSUNG_STOP_BIT, // stop_bit: flag: frame has stop bit
SAMSUNG_LSB, // lsb_first: flag: LSB first
SAMSUNG_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER samsungah_param =
{
IRMP_SAMSUNGAH_PROTOCOL, // protocol: ir protocol
SAMSUNGAH_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
SAMSUNGAH_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
SAMSUNGAH_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
SAMSUNGAH_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
SAMSUNGAH_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
SAMSUNGAH_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
SAMSUNGAH_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
SAMSUNGAH_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
SAMSUNGAH_ADDRESS_OFFSET, // address_offset: address offset
SAMSUNGAH_ADDRESS_OFFSET + SAMSUNGAH_ADDRESS_LEN, // address_end: end of address
SAMSUNGAH_COMMAND_OFFSET, // command_offset: command offset
SAMSUNGAH_COMMAND_OFFSET + SAMSUNGAH_COMMAND_LEN, // command_end: end of command
SAMSUNGAH_COMPLETE_DATA_LEN, // complete_len: complete length of frame
SAMSUNGAH_STOP_BIT, // stop_bit: flag: frame has stop bit
SAMSUNGAH_LSB, // lsb_first: flag: LSB first
SAMSUNGAH_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER telefunken_param =
{
IRMP_TELEFUNKEN_PROTOCOL, // protocol: ir protocol
TELEFUNKEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
TELEFUNKEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
TELEFUNKEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
TELEFUNKEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
TELEFUNKEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
TELEFUNKEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
TELEFUNKEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
TELEFUNKEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
TELEFUNKEN_ADDRESS_OFFSET, // address_offset: address offset
TELEFUNKEN_ADDRESS_OFFSET + TELEFUNKEN_ADDRESS_LEN, // address_end: end of address
TELEFUNKEN_COMMAND_OFFSET, // command_offset: command offset
TELEFUNKEN_COMMAND_OFFSET + TELEFUNKEN_COMMAND_LEN, // command_end: end of command
TELEFUNKEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame
TELEFUNKEN_STOP_BIT, // stop_bit: flag: frame has stop bit
TELEFUNKEN_LSB, // lsb_first: flag: LSB first
TELEFUNKEN_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER matsushita_param =
{
IRMP_MATSUSHITA_PROTOCOL, // protocol: ir protocol
MATSUSHITA_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
MATSUSHITA_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
MATSUSHITA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
MATSUSHITA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
MATSUSHITA_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
MATSUSHITA_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
MATSUSHITA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
MATSUSHITA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
MATSUSHITA_ADDRESS_OFFSET, // address_offset: address offset
MATSUSHITA_ADDRESS_OFFSET + MATSUSHITA_ADDRESS_LEN, // address_end: end of address
MATSUSHITA_COMMAND_OFFSET, // command_offset: command offset
MATSUSHITA_COMMAND_OFFSET + MATSUSHITA_COMMAND_LEN, // command_end: end of command
MATSUSHITA_COMPLETE_DATA_LEN, // complete_len: complete length of frame
MATSUSHITA_STOP_BIT, // stop_bit: flag: frame has stop bit
MATSUSHITA_LSB, // lsb_first: flag: LSB first
MATSUSHITA_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER kaseikyo_param =
{
IRMP_KASEIKYO_PROTOCOL, // protocol: ir protocol
KASEIKYO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
KASEIKYO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
KASEIKYO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
KASEIKYO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
KASEIKYO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
KASEIKYO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
KASEIKYO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
KASEIKYO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
KASEIKYO_ADDRESS_OFFSET, // address_offset: address offset
KASEIKYO_ADDRESS_OFFSET + KASEIKYO_ADDRESS_LEN, // address_end: end of address
KASEIKYO_COMMAND_OFFSET, // command_offset: command offset
KASEIKYO_COMMAND_OFFSET + KASEIKYO_COMMAND_LEN, // command_end: end of command
KASEIKYO_COMPLETE_DATA_LEN, // complete_len: complete length of frame
KASEIKYO_STOP_BIT, // stop_bit: flag: frame has stop bit
KASEIKYO_LSB, // lsb_first: flag: LSB first
KASEIKYO_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER panasonic_param =
{
IRMP_PANASONIC_PROTOCOL, // protocol: ir protocol
PANASONIC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
PANASONIC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
PANASONIC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
PANASONIC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
PANASONIC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
PANASONIC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
PANASONIC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
PANASONIC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
PANASONIC_ADDRESS_OFFSET, // address_offset: address offset
PANASONIC_ADDRESS_OFFSET + PANASONIC_ADDRESS_LEN, // address_end: end of address
PANASONIC_COMMAND_OFFSET, // command_offset: command offset
PANASONIC_COMMAND_OFFSET + PANASONIC_COMMAND_LEN, // command_end: end of command
PANASONIC_COMPLETE_DATA_LEN, // complete_len: complete length of frame
PANASONIC_STOP_BIT, // stop_bit: flag: frame has stop bit
PANASONIC_LSB, // lsb_first: flag: LSB first
PANASONIC_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER mitsu_heavy_param =
{
IRMP_MITSU_HEAVY_PROTOCOL, // protocol: ir protocol
MITSU_HEAVY_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
MITSU_HEAVY_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
MITSU_HEAVY_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
MITSU_HEAVY_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
MITSU_HEAVY_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
MITSU_HEAVY_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
MITSU_HEAVY_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
MITSU_HEAVY_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
MITSU_HEAVY_ADDRESS_OFFSET, // address_offset: address offset
MITSU_HEAVY_ADDRESS_OFFSET + MITSU_HEAVY_ADDRESS_LEN, // address_end: end of address
MITSU_HEAVY_COMMAND_OFFSET, // command_offset: command offset
MITSU_HEAVY_COMMAND_OFFSET + MITSU_HEAVY_COMMAND_LEN, // command_end: end of command
MITSU_HEAVY_COMPLETE_DATA_LEN, // complete_len: complete length of frame
MITSU_HEAVY_STOP_BIT, // stop_bit: flag: frame has stop bit
MITSU_HEAVY_LSB, // lsb_first: flag: LSB first
MITSU_HEAVY_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER vincent_param =
{
IRMP_VINCENT_PROTOCOL, // protocol: ir protocol
VINCENT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
VINCENT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
VINCENT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
VINCENT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
VINCENT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
VINCENT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
VINCENT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
VINCENT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
VINCENT_ADDRESS_OFFSET, // address_offset: address offset
VINCENT_ADDRESS_OFFSET + VINCENT_ADDRESS_LEN, // address_end: end of address
VINCENT_COMMAND_OFFSET, // command_offset: command offset
VINCENT_COMMAND_OFFSET + VINCENT_COMMAND_LEN, // command_end: end of command
VINCENT_COMPLETE_DATA_LEN, // complete_len: complete length of frame
VINCENT_STOP_BIT, // stop_bit: flag: frame has stop bit
VINCENT_LSB, // lsb_first: flag: LSB first
VINCENT_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RECS80_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER recs80_param =
{
IRMP_RECS80_PROTOCOL, // protocol: ir protocol
RECS80_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RECS80_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RECS80_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RECS80_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RECS80_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RECS80_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RECS80_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RECS80_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RECS80_ADDRESS_OFFSET, // address_offset: address offset
RECS80_ADDRESS_OFFSET + RECS80_ADDRESS_LEN, // address_end: end of address
RECS80_COMMAND_OFFSET, // command_offset: command offset
RECS80_COMMAND_OFFSET + RECS80_COMMAND_LEN, // command_end: end of command
RECS80_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RECS80_STOP_BIT, // stop_bit: flag: frame has stop bit
RECS80_LSB, // lsb_first: flag: LSB first
RECS80_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rc5_param =
{
IRMP_RC5_PROTOCOL, // protocol: ir protocol
RC5_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
RC5_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
RC5_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
RC5_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
RC5_ADDRESS_OFFSET, // address_offset: address offset
RC5_ADDRESS_OFFSET + RC5_ADDRESS_LEN, // address_end: end of address
RC5_COMMAND_OFFSET, // command_offset: command offset
RC5_COMMAND_OFFSET + RC5_COMMAND_LEN, // command_end: end of command
RC5_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RC5_STOP_BIT, // stop_bit: flag: frame has stop bit
RC5_LSB, // lsb_first: flag: LSB first
RC5_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rcii_param =
{
IRMP_RCII_PROTOCOL, // protocol: ir protocol
RCII_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
RCII_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
RCII_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
RCII_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
RCII_BIT_LEN_MIN, // pulse_0_len_min: here: not used
RCII_BIT_LEN_MAX, // pulse_0_len_max: here: not used
RCII_BIT_LEN_MIN, // pause_0_len_min: here: not used
RCII_BIT_LEN_MAX, // pause_0_len_max: here: not used
RCII_ADDRESS_OFFSET, // address_offset: address offset
RCII_ADDRESS_OFFSET + RCII_ADDRESS_LEN, // address_end: end of address
RCII_COMMAND_OFFSET, // command_offset: command offset
RCII_COMMAND_OFFSET + RCII_COMMAND_LEN, // command_end: end of command
RCII_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RCII_STOP_BIT, // stop_bit: flag: frame has stop bit
RCII_LSB, // lsb_first: flag: LSB first
RCII_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_S100_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER s100_param =
{
IRMP_S100_PROTOCOL, // protocol: ir protocol
S100_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
S100_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
S100_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
S100_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
S100_ADDRESS_OFFSET, // address_offset: address offset
S100_ADDRESS_OFFSET + S100_ADDRESS_LEN, // address_end: end of address
S100_COMMAND_OFFSET, // command_offset: command offset
S100_COMMAND_OFFSET + S100_COMMAND_LEN, // command_end: end of command
S100_COMPLETE_DATA_LEN, // complete_len: complete length of frame
S100_STOP_BIT, // stop_bit: flag: frame has stop bit
S100_LSB, // lsb_first: flag: LSB first
S100_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER denon_param =
{
IRMP_DENON_PROTOCOL, // protocol: ir protocol
DENON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
DENON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
DENON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
DENON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
DENON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
DENON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
DENON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
DENON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
DENON_ADDRESS_OFFSET, // address_offset: address offset
DENON_ADDRESS_OFFSET + DENON_ADDRESS_LEN, // address_end: end of address
DENON_COMMAND_OFFSET, // command_offset: command offset
DENON_COMMAND_OFFSET + DENON_COMMAND_LEN, // command_end: end of command
DENON_COMPLETE_DATA_LEN, // complete_len: complete length of frame
DENON_STOP_BIT, // stop_bit: flag: frame has stop bit
DENON_LSB, // lsb_first: flag: LSB first
DENON_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rc6_param =
{
IRMP_RC6_PROTOCOL, // protocol: ir protocol
RC6_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
RC6_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
RC6_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
RC6_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
RC6_ADDRESS_OFFSET, // address_offset: address offset
RC6_ADDRESS_OFFSET + RC6_ADDRESS_LEN, // address_end: end of address
RC6_COMMAND_OFFSET, // command_offset: command offset
RC6_COMMAND_OFFSET + RC6_COMMAND_LEN, // command_end: end of command
RC6_COMPLETE_DATA_LEN_SHORT, // complete_len: complete length of frame
RC6_STOP_BIT, // stop_bit: flag: frame has stop bit
RC6_LSB, // lsb_first: flag: LSB first
RC6_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER recs80ext_param =
{
IRMP_RECS80EXT_PROTOCOL, // protocol: ir protocol
RECS80EXT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RECS80EXT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RECS80EXT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RECS80EXT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RECS80EXT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RECS80EXT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RECS80EXT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RECS80EXT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RECS80EXT_ADDRESS_OFFSET, // address_offset: address offset
RECS80EXT_ADDRESS_OFFSET + RECS80EXT_ADDRESS_LEN, // address_end: end of address
RECS80EXT_COMMAND_OFFSET, // command_offset: command offset
RECS80EXT_COMMAND_OFFSET + RECS80EXT_COMMAND_LEN, // command_end: end of command
RECS80EXT_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RECS80EXT_STOP_BIT, // stop_bit: flag: frame has stop bit
RECS80EXT_LSB, // lsb_first: flag: LSB first
RECS80EXT_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER nubert_param =
{
IRMP_NUBERT_PROTOCOL, // protocol: ir protocol
NUBERT_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NUBERT_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NUBERT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NUBERT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NUBERT_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NUBERT_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NUBERT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NUBERT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
NUBERT_ADDRESS_OFFSET, // address_offset: address offset
NUBERT_ADDRESS_OFFSET + NUBERT_ADDRESS_LEN, // address_end: end of address
NUBERT_COMMAND_OFFSET, // command_offset: command offset
NUBERT_COMMAND_OFFSET + NUBERT_COMMAND_LEN, // command_end: end of command
NUBERT_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NUBERT_STOP_BIT, // stop_bit: flag: frame has stop bit
NUBERT_LSB, // lsb_first: flag: LSB first
NUBERT_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_FAN_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER fan_param =
{
IRMP_FAN_PROTOCOL, // protocol: ir protocol
FAN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
FAN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
FAN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
FAN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
FAN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
FAN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
FAN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
FAN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
FAN_ADDRESS_OFFSET, // address_offset: address offset
FAN_ADDRESS_OFFSET + FAN_ADDRESS_LEN, // address_end: end of address
FAN_COMMAND_OFFSET, // command_offset: command offset
FAN_COMMAND_OFFSET + FAN_COMMAND_LEN, // command_end: end of command
FAN_COMPLETE_DATA_LEN, // complete_len: complete length of frame
FAN_STOP_BIT, // stop_bit: flag: frame has NO stop bit
FAN_LSB, // lsb_first: flag: LSB first
FAN_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER speaker_param =
{
IRMP_SPEAKER_PROTOCOL, // protocol: ir protocol
SPEAKER_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
SPEAKER_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
SPEAKER_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
SPEAKER_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
SPEAKER_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
SPEAKER_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
SPEAKER_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
SPEAKER_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
SPEAKER_ADDRESS_OFFSET, // address_offset: address offset
SPEAKER_ADDRESS_OFFSET + SPEAKER_ADDRESS_LEN, // address_end: end of address
SPEAKER_COMMAND_OFFSET, // command_offset: command offset
SPEAKER_COMMAND_OFFSET + SPEAKER_COMMAND_LEN, // command_end: end of command
SPEAKER_COMPLETE_DATA_LEN, // complete_len: complete length of frame
SPEAKER_STOP_BIT, // stop_bit: flag: frame has stop bit
SPEAKER_LSB, // lsb_first: flag: LSB first
SPEAKER_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER bang_olufsen_param =
{
IRMP_BANG_OLUFSEN_PROTOCOL, // protocol: ir protocol
BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
BANG_OLUFSEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
BANG_OLUFSEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
BANG_OLUFSEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
BANG_OLUFSEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
BANG_OLUFSEN_ADDRESS_OFFSET, // address_offset: address offset
BANG_OLUFSEN_ADDRESS_OFFSET + BANG_OLUFSEN_ADDRESS_LEN, // address_end: end of address
BANG_OLUFSEN_COMMAND_OFFSET, // command_offset: command offset
BANG_OLUFSEN_COMMAND_OFFSET + BANG_OLUFSEN_COMMAND_LEN, // command_end: end of command
BANG_OLUFSEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame
BANG_OLUFSEN_STOP_BIT, // stop_bit: flag: frame has stop bit
BANG_OLUFSEN_LSB, // lsb_first: flag: LSB first
BANG_OLUFSEN_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1
static uint_fast8_t first_bit;
static const PROGMEM IRMP_PARAMETER grundig_param =
{
IRMP_GRUNDIG_PROTOCOL, // protocol: ir protocol
GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
GRUNDIG_ADDRESS_OFFSET, // address_offset: address offset
GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN, // address_end: end of address
GRUNDIG_COMMAND_OFFSET, // command_offset: command offset
GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN + 1, // command_end: end of command (USE 1 bit MORE to STORE NOKIA DATA!)
NOKIA_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: NOKIA instead of GRUNDIG!
GRUNDIG_NOKIA_IR60_STOP_BIT, // stop_bit: flag: frame has stop bit
GRUNDIG_NOKIA_IR60_LSB, // lsb_first: flag: LSB first
GRUNDIG_NOKIA_IR60_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER ruwido_param =
{
IRMP_RUWIDO_PROTOCOL, // protocol: ir protocol
SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
RUWIDO_ADDRESS_OFFSET, // address_offset: address offset
RUWIDO_ADDRESS_OFFSET + RUWIDO_ADDRESS_LEN, // address_end: end of address
RUWIDO_COMMAND_OFFSET, // command_offset: command offset
RUWIDO_COMMAND_OFFSET + RUWIDO_COMMAND_LEN, // command_end: end of command
SIEMENS_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: SIEMENS instead of RUWIDO!
SIEMENS_OR_RUWIDO_STOP_BIT, // stop_bit: flag: frame has stop bit
SIEMENS_OR_RUWIDO_LSB, // lsb_first: flag: LSB first
SIEMENS_OR_RUWIDO_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER fdc_param =
{
IRMP_FDC_PROTOCOL, // protocol: ir protocol
FDC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
FDC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
FDC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
FDC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
FDC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
FDC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
FDC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
FDC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
FDC_ADDRESS_OFFSET, // address_offset: address offset
FDC_ADDRESS_OFFSET + FDC_ADDRESS_LEN, // address_end: end of address
FDC_COMMAND_OFFSET, // command_offset: command offset
FDC_COMMAND_OFFSET + FDC_COMMAND_LEN, // command_end: end of command
FDC_COMPLETE_DATA_LEN, // complete_len: complete length of frame
FDC_STOP_BIT, // stop_bit: flag: frame has stop bit
FDC_LSB, // lsb_first: flag: LSB first
FDC_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rccar_param =
{
IRMP_RCCAR_PROTOCOL, // protocol: ir protocol
RCCAR_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RCCAR_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RCCAR_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RCCAR_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RCCAR_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RCCAR_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RCCAR_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RCCAR_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RCCAR_ADDRESS_OFFSET, // address_offset: address offset
RCCAR_ADDRESS_OFFSET + RCCAR_ADDRESS_LEN, // address_end: end of address
RCCAR_COMMAND_OFFSET, // command_offset: command offset
RCCAR_COMMAND_OFFSET + RCCAR_COMMAND_LEN, // command_end: end of command
RCCAR_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RCCAR_STOP_BIT, // stop_bit: flag: frame has stop bit
RCCAR_LSB, // lsb_first: flag: LSB first
RCCAR_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER nikon_param =
{
IRMP_NIKON_PROTOCOL, // protocol: ir protocol
NIKON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
NIKON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
NIKON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
NIKON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
NIKON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
NIKON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
NIKON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
NIKON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
NIKON_ADDRESS_OFFSET, // address_offset: address offset
NIKON_ADDRESS_OFFSET + NIKON_ADDRESS_LEN, // address_end: end of address
NIKON_COMMAND_OFFSET, // command_offset: command offset
NIKON_COMMAND_OFFSET + NIKON_COMMAND_LEN, // command_end: end of command
NIKON_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NIKON_STOP_BIT, // stop_bit: flag: frame has stop bit
NIKON_LSB, // lsb_first: flag: LSB first
NIKON_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER kathrein_param =
{
IRMP_KATHREIN_PROTOCOL, // protocol: ir protocol
KATHREIN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
KATHREIN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
KATHREIN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
KATHREIN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
KATHREIN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
KATHREIN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
KATHREIN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
KATHREIN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
KATHREIN_ADDRESS_OFFSET, // address_offset: address offset
KATHREIN_ADDRESS_OFFSET + KATHREIN_ADDRESS_LEN, // address_end: end of address
KATHREIN_COMMAND_OFFSET, // command_offset: command offset
KATHREIN_COMMAND_OFFSET + KATHREIN_COMMAND_LEN, // command_end: end of command
KATHREIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame
KATHREIN_STOP_BIT, // stop_bit: flag: frame has stop bit
KATHREIN_LSB, // lsb_first: flag: LSB first
KATHREIN_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER netbox_param =
{
IRMP_NETBOX_PROTOCOL, // protocol: ir protocol
NETBOX_PULSE_LEN, // pulse_1_len_min: minimum length of pulse with bit value 1, here: exact value
NETBOX_PULSE_REST_LEN, // pulse_1_len_max: maximum length of pulse with bit value 1, here: rest value
NETBOX_PAUSE_LEN, // pause_1_len_min: minimum length of pause with bit value 1, here: exact value
NETBOX_PAUSE_REST_LEN, // pause_1_len_max: maximum length of pause with bit value 1, here: rest value
NETBOX_PULSE_LEN, // pulse_0_len_min: minimum length of pulse with bit value 0, here: exact value
NETBOX_PULSE_REST_LEN, // pulse_0_len_max: maximum length of pulse with bit value 0, here: rest value
NETBOX_PAUSE_LEN, // pause_0_len_min: minimum length of pause with bit value 0, here: exact value
NETBOX_PAUSE_REST_LEN, // pause_0_len_max: maximum length of pause with bit value 0, here: rest value
NETBOX_ADDRESS_OFFSET, // address_offset: address offset
NETBOX_ADDRESS_OFFSET + NETBOX_ADDRESS_LEN, // address_end: end of address
NETBOX_COMMAND_OFFSET, // command_offset: command offset
NETBOX_COMMAND_OFFSET + NETBOX_COMMAND_LEN, // command_end: end of command
NETBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame
NETBOX_STOP_BIT, // stop_bit: flag: frame has stop bit
NETBOX_LSB, // lsb_first: flag: LSB first
NETBOX_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER lego_param =
{
IRMP_LEGO_PROTOCOL, // protocol: ir protocol
LEGO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
LEGO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
LEGO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
LEGO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
LEGO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
LEGO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
LEGO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
LEGO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
LEGO_ADDRESS_OFFSET, // address_offset: address offset
LEGO_ADDRESS_OFFSET + LEGO_ADDRESS_LEN, // address_end: end of address
LEGO_COMMAND_OFFSET, // command_offset: command offset
LEGO_COMMAND_OFFSET + LEGO_COMMAND_LEN, // command_end: end of command
LEGO_COMPLETE_DATA_LEN, // complete_len: complete length of frame
LEGO_STOP_BIT, // stop_bit: flag: frame has stop bit
LEGO_LSB, // lsb_first: flag: LSB first
LEGO_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER irmp16_param =
{
IRMP_IRMP16_PROTOCOL, // protocol: ir protocol
IRMP16_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
IRMP16_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
IRMP16_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
IRMP16_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
IRMP16_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
IRMP16_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
IRMP16_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
IRMP16_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
IRMP16_ADDRESS_OFFSET, // address_offset: address offset
IRMP16_ADDRESS_OFFSET + IRMP16_ADDRESS_LEN, // address_end: end of address
IRMP16_COMMAND_OFFSET, // command_offset: command offset
IRMP16_COMMAND_OFFSET + IRMP16_COMMAND_LEN, // command_end: end of command
IRMP16_COMPLETE_DATA_LEN, // complete_len: complete length of frame
IRMP16_STOP_BIT, // stop_bit: flag: frame has stop bit
IRMP16_LSB, // lsb_first: flag: LSB first
IRMP16_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_GREE_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER gree_param =
{
IRMP_GREE_PROTOCOL, // protocol: ir protocol
GREE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
GREE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
GREE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
GREE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
GREE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
GREE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
GREE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
GREE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
GREE_ADDRESS_OFFSET, // address_offset: address offset
GREE_ADDRESS_OFFSET + GREE_ADDRESS_LEN, // address_end: end of address
GREE_COMMAND_OFFSET, // command_offset: command offset
GREE_COMMAND_OFFSET + GREE_COMMAND_LEN, // command_end: end of command
GREE_COMPLETE_DATA_LEN, // complete_len: complete length of frame
GREE_STOP_BIT, // stop_bit: flag: frame has stop bit
GREE_LSB, // lsb_first: flag: LSB first
GREE_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER thomson_param =
{
IRMP_THOMSON_PROTOCOL, // protocol: ir protocol
THOMSON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
THOMSON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
THOMSON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
THOMSON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
THOMSON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
THOMSON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
THOMSON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
THOMSON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
THOMSON_ADDRESS_OFFSET, // address_offset: address offset
THOMSON_ADDRESS_OFFSET + THOMSON_ADDRESS_LEN, // address_end: end of address
THOMSON_COMMAND_OFFSET, // command_offset: command offset
THOMSON_COMMAND_OFFSET + THOMSON_COMMAND_LEN, // command_end: end of command
THOMSON_COMPLETE_DATA_LEN, // complete_len: complete length of frame
THOMSON_STOP_BIT, // stop_bit: flag: frame has stop bit
THOMSON_LSB, // lsb_first: flag: LSB first
THOMSON_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER bose_param =
{
IRMP_BOSE_PROTOCOL, // protocol: ir protocol
BOSE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
BOSE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
BOSE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
BOSE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
BOSE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
BOSE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
BOSE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
BOSE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
BOSE_ADDRESS_OFFSET, // address_offset: address offset
BOSE_ADDRESS_OFFSET + BOSE_ADDRESS_LEN, // address_end: end of address
BOSE_COMMAND_OFFSET, // command_offset: command offset
BOSE_COMMAND_OFFSET + BOSE_COMMAND_LEN, // command_end: end of command
BOSE_COMPLETE_DATA_LEN, // complete_len: complete length of frame
BOSE_STOP_BIT, // stop_bit: flag: frame has stop bit
BOSE_LSB, // lsb_first: flag: LSB first
BOSE_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER a1tvbox_param =
{
IRMP_A1TVBOX_PROTOCOL, // protocol: ir protocol
A1TVBOX_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
A1TVBOX_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
A1TVBOX_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
A1TVBOX_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
A1TVBOX_ADDRESS_OFFSET, // address_offset: address offset
A1TVBOX_ADDRESS_OFFSET + A1TVBOX_ADDRESS_LEN, // address_end: end of address
A1TVBOX_COMMAND_OFFSET, // command_offset: command offset
A1TVBOX_COMMAND_OFFSET + A1TVBOX_COMMAND_LEN, // command_end: end of command
A1TVBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame
A1TVBOX_STOP_BIT, // stop_bit: flag: frame has stop bit
A1TVBOX_LSB, // lsb_first: flag: LSB first
A1TVBOX_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER merlin_param =
{
IRMP_MERLIN_PROTOCOL, // protocol: ir protocol
MERLIN_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
MERLIN_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
MERLIN_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
MERLIN_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
MERLIN_ADDRESS_OFFSET, // address_offset: address offset
MERLIN_ADDRESS_OFFSET + MERLIN_ADDRESS_LEN, // address_end: end of address
MERLIN_COMMAND_OFFSET, // command_offset: command offset
MERLIN_COMMAND_OFFSET + MERLIN_COMMAND_LEN, // command_end: end of command
MERLIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame
MERLIN_STOP_BIT, // stop_bit: flag: frame has stop bit
MERLIN_LSB, // lsb_first: flag: LSB first
MERLIN_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER ortek_param =
{
IRMP_ORTEK_PROTOCOL, // protocol: ir protocol
ORTEK_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
ORTEK_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
ORTEK_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause
ORTEK_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause
0, // pulse_0_len_min: here: not used
0, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
ORTEK_ADDRESS_OFFSET, // address_offset: address offset
ORTEK_ADDRESS_OFFSET + ORTEK_ADDRESS_LEN, // address_end: end of address
ORTEK_COMMAND_OFFSET, // command_offset: command offset
ORTEK_COMMAND_OFFSET + ORTEK_COMMAND_LEN, // command_end: end of command
ORTEK_COMPLETE_DATA_LEN, // complete_len: complete length of frame
ORTEK_STOP_BIT, // stop_bit: flag: frame has stop bit
ORTEK_LSB, // lsb_first: flag: LSB first
ORTEK_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER roomba_param =
{
IRMP_ROOMBA_PROTOCOL, // protocol: ir protocol
ROOMBA_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
ROOMBA_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
ROOMBA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
ROOMBA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
ROOMBA_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
ROOMBA_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
ROOMBA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
ROOMBA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
ROOMBA_ADDRESS_OFFSET, // address_offset: address offset
ROOMBA_ADDRESS_OFFSET + ROOMBA_ADDRESS_LEN, // address_end: end of address
ROOMBA_COMMAND_OFFSET, // command_offset: command offset
ROOMBA_COMMAND_OFFSET + ROOMBA_COMMAND_LEN, // command_end: end of command
ROOMBA_COMPLETE_DATA_LEN, // complete_len: complete length of frame
ROOMBA_STOP_BIT, // stop_bit: flag: frame has stop bit
ROOMBA_LSB, // lsb_first: flag: LSB first
ROOMBA_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rcmm_param =
{
IRMP_RCMM32_PROTOCOL, // protocol: ir protocol
RCMM32_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse
RCMM32_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse
0, // pause_1_len_min: here: minimum length of short pause
0, // pause_1_len_max: here: maximum length of short pause
RCMM32_BIT_PULSE_LEN_MIN, // pulse_0_len_min: here: not used
RCMM32_BIT_PULSE_LEN_MAX, // pulse_0_len_max: here: not used
0, // pause_0_len_min: here: not used
0, // pause_0_len_max: here: not used
RCMM32_ADDRESS_OFFSET, // address_offset: address offset
RCMM32_ADDRESS_OFFSET + RCMM32_ADDRESS_LEN, // address_end: end of address
RCMM32_COMMAND_OFFSET, // command_offset: command offset
RCMM32_COMMAND_OFFSET + RCMM32_COMMAND_LEN, // command_end: end of command
RCMM32_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RCMM32_STOP_BIT, // stop_bit: flag: frame has stop bit
RCMM32_LSB, // lsb_first: flag: LSB first
RCMM32_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER pentax_param =
{
IRMP_PENTAX_PROTOCOL, // protocol: ir protocol
PENTAX_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
PENTAX_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
PENTAX_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
PENTAX_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
PENTAX_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
PENTAX_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
PENTAX_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
PENTAX_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
PENTAX_ADDRESS_OFFSET, // address_offset: address offset
PENTAX_ADDRESS_OFFSET + PENTAX_ADDRESS_LEN, // address_end: end of address
PENTAX_COMMAND_OFFSET, // command_offset: command offset
PENTAX_COMMAND_OFFSET + PENTAX_COMMAND_LEN, // command_end: end of command
PENTAX_COMPLETE_DATA_LEN, // complete_len: complete length of frame
PENTAX_STOP_BIT, // stop_bit: flag: frame has stop bit
PENTAX_LSB, // lsb_first: flag: LSB first
PENTAX_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_ACP24_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER acp24_param =
{
IRMP_ACP24_PROTOCOL, // protocol: ir protocol
ACP24_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
ACP24_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
ACP24_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
ACP24_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
ACP24_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
ACP24_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
ACP24_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
ACP24_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
ACP24_ADDRESS_OFFSET, // address_offset: address offset
ACP24_ADDRESS_OFFSET + ACP24_ADDRESS_LEN, // address_end: end of address
ACP24_COMMAND_OFFSET, // command_offset: command offset
ACP24_COMMAND_OFFSET + ACP24_COMMAND_LEN, // command_end: end of command
ACP24_COMPLETE_DATA_LEN, // complete_len: complete length of frame
ACP24_STOP_BIT, // stop_bit: flag: frame has stop bit
ACP24_LSB, // lsb_first: flag: LSB first
ACP24_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_METZ_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER metz_param =
{
IRMP_METZ_PROTOCOL, // protocol: ir protocol
METZ_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
METZ_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
METZ_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
METZ_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
METZ_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
METZ_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
METZ_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
METZ_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
METZ_ADDRESS_OFFSET, // address_offset: address offset
METZ_ADDRESS_OFFSET + METZ_ADDRESS_LEN, // address_end: end of address
METZ_COMMAND_OFFSET, // command_offset: command offset
METZ_COMMAND_OFFSET + METZ_COMMAND_LEN, // command_end: end of command
METZ_COMPLETE_DATA_LEN, // complete_len: complete length of frame
METZ_STOP_BIT, // stop_bit: flag: frame has stop bit
METZ_LSB, // lsb_first: flag: LSB first
METZ_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rf_gen24_param =
{
RF_GEN24_PROTOCOL, // protocol: ir protocol
RF_GEN24_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RF_GEN24_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RF_GEN24_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RF_GEN24_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RF_GEN24_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RF_GEN24_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RF_GEN24_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RF_GEN24_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RF_GEN24_ADDRESS_OFFSET, // address_offset: address offset
RF_GEN24_ADDRESS_OFFSET + RF_GEN24_ADDRESS_LEN, // address_end: end of address
RF_GEN24_COMMAND_OFFSET, // command_offset: command offset
RF_GEN24_COMMAND_OFFSET + RF_GEN24_COMMAND_LEN, // command_end: end of command
RF_GEN24_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RF_GEN24_STOP_BIT, // stop_bit: flag: frame has stop bit
RF_GEN24_LSB, // lsb_first: flag: LSB first
RF_GEN24_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rf_x10_param =
{
RF_X10_PROTOCOL, // protocol: ir protocol
RF_X10_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RF_X10_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RF_X10_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RF_X10_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RF_X10_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RF_X10_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RF_X10_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RF_X10_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RF_X10_ADDRESS_OFFSET, // address_offset: address offset
RF_X10_ADDRESS_OFFSET + RF_X10_ADDRESS_LEN, // address_end: end of address
RF_X10_COMMAND_OFFSET, // command_offset: command offset
RF_X10_COMMAND_OFFSET + RF_X10_COMMAND_LEN, // command_end: end of command
RF_X10_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RF_X10_STOP_BIT, // stop_bit: flag: frame has stop bit
RF_X10_LSB, // lsb_first: flag: LSB first
RF_X10_FLAGS // flags: some flags
};
#endif
#if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
static const PROGMEM IRMP_PARAMETER rf_medion_param =
{
RF_MEDION_PROTOCOL, // protocol: ir protocol
RF_MEDION_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1
RF_MEDION_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1
RF_MEDION_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1
RF_MEDION_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1
RF_MEDION_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0
RF_MEDION_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0
RF_MEDION_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0
RF_MEDION_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0
RF_MEDION_ADDRESS_OFFSET, // address_offset: address offset
RF_MEDION_ADDRESS_OFFSET + RF_MEDION_ADDRESS_LEN, // address_end: end of address
RF_MEDION_COMMAND_OFFSET, // command_offset: command offset
RF_MEDION_COMMAND_OFFSET + RF_MEDION_COMMAND_LEN, // command_end: end of command
RF_MEDION_COMPLETE_DATA_LEN, // complete_len: complete length of frame
RF_MEDION_STOP_BIT, // stop_bit: flag: frame has stop bit
RF_MEDION_LSB, // lsb_first: flag: LSB first
RF_MEDION_FLAGS // flags: some flags
};
#endif
static uint_fast8_t irmp_bit; // current bit position
static IRMP_PARAMETER irmp_param;
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
static IRMP_PARAMETER irmp_param2;
#endif
static volatile uint_fast8_t irmp_ir_detected = FALSE;
static volatile uint_fast8_t irmp_protocol;
static volatile uint_fast16_t irmp_address;
#if IRMP_32_BIT == 1
static uint_fast32_t irmp_command;
#else
static uint_fast16_t irmp_command; // removed volatile, because it is only used in irmp_get_data and therefore volatile makes no sense
#endif
static volatile uint_fast16_t irmp_id; // only used for SAMSUNG protocol
static uint_fast8_t irmp_flags; // removed volatile, because it is only used in irmp_get_data and therefore volatile makes no sense
// static volatile uint_fast8_t irmp_busy_flag;
#if IRMP_AUTODETECT_REPEATRATE
volatile uint_fast16_t delta_detection = 0; // interval between two detections in ticks
volatile uint32_t pass_on_delta_detection = 0xFFFF; // interval between two detections in ticks
volatile uint_fast16_t tmp_delta = 0xFFFF;
volatile uint_fast8_t delta = 0; // interval between two detections in ms
volatile uint_fast8_t min_delta = 170; // detected repeat rate, preset to greatest known repeat rate
static volatile uint_fast8_t previous_irmp_protocol = 0;
volatile uint_fast8_t same_key = 0;
volatile uint_fast8_t keep_same_key = 0;
volatile uint_fast8_t timeout = 1;
volatile uint_fast8_t upper_border = 176; // repeatrate plus jitter (threshold for timeout)
#endif
#if defined(__MBED__)
// DigitalIn inputPin(IRMP_PIN, PullUp); // this requires mbed.h and source to be compiled as cpp
gpio_t gpioIRin; // use low level c function instead
#endif
#if defined(ANALYZE)
#define input(x) (x)
static uint_fast8_t IRMP_PIN;
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Initialize IRMP decoder
* @details Configures IRMP input pin
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(ANALYZE)
#if ! defined(ARDUINO)
void
irmp_init (void)
{
#if defined(PIC_CCS) || defined(PIC_C18) // PIC: do nothing
#elif defined(PIC_XC32)
# if defined(IRMP_ANSELBIT)
IRMP_ANSELBIT = 0;
# endif
#elif defined (ARM_STM32_HAL) // STM32 with Hal Library: do nothing
#elif defined (ARM_STM32) // STM32
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOx clock enable */
# if defined (ARM_STM32L1XX)
RCC_AHBPeriphClockCmd(IRMP_PORT_RCC, ENABLE);
# elif defined (ARM_STM32F10X)
RCC_APB2PeriphClockCmd(IRMP_PORT_RCC, ENABLE);
# elif defined (ARM_STM32F30X)
RCC_AHBPeriphClockCmd(IRMP_PORT_RCC, ENABLE);
# elif defined (ARM_STM32F4XX)
RCC_AHB1PeriphClockCmd(IRMP_PORT_RCC, ENABLE);
# endif
/* GPIO Configuration */
GPIO_InitStructure.GPIO_Pin = IRMP_BIT;
# if defined (ARM_STM32L1XX) || defined (ARM_STM32F4XX)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
# elif defined (ARM_STM32F10X)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
# elif defined (ARM_STM32F30X)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
# endif
GPIO_Init(IRMP_PORT, &GPIO_InitStructure);
#elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3
/* GPIOx clock enable */
# if defined (STM32L1) || defined (STM32F1) || defined (STM32F3) || defined (STM32F4)
rcc_periph_clock_enable(IRMP_PORT_RCC);
# endif
/* GPIO Configuration */
# if defined (STM32L1) || defined (STM32F4) || defined (STM32F3)
gpio_mode_setup(IRMP_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, IRMP_BIT);
gpio_set_output_options(IRMP_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRMP_BIT);
# elif defined (STM32F1)
gpio_set_mode(IRMP_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, IRMP_BIT);
# endif
#elif defined(STELLARIS_ARM_CORTEX_M4)
// Enable the GPIO port
ROM_SysCtlPeripheralEnable(IRMP_PORT_PERIPH);
// Set as an input
ROM_GPIODirModeSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_DIR_MODE_IN);
ROM_GPIOPadConfigSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
#elif defined(__SDCC_stm8) // STM8
IRMP_GPIO_STRUCT->DDR &= ~(1<CR1 |= (1<> 8) == (~irmp_command & 0x00FF))
{
irmp_command &= 0xff;
// irmp_command |= irmp_id << 8; // for samsung32 irmp_id looks to be the same as irmp_command
tReturnCode = TRUE;
}
break;
# if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
case IRMP_SAMSUNG48_PROTOCOL:
irmp_command = (irmp_command & 0x00FF) | ((irmp_id & 0x00FF) << 8);
tReturnCode = TRUE;
break;
# endif
#endif
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
case IRMP_SIRCS_PROTOCOL:
// Concatenate high byte of command and low byte of address
irmp_address <<= 7;
irmp_address = irmp_address | irmp_command >> 8;
// Command is 7 bytes, so add the 8.th bit of command to address
irmp_address <<= 1;
if ((irmp_command & 0x80))
{
irmp_address++;
}
irmp_command &= 0x7F;
tReturnCode = TRUE;
break;
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
case IRMP_NEC_PROTOCOL:
if ((irmp_command >> 8) == (~irmp_command & 0x00FF))
{
if ((irmp_address >> 8) == (~irmp_address & 0x00FF))
{
irmp_address &= 0xff;
}
irmp_command &= 0xff;
}
else if (irmp_address == 0x87EE)
{
ANALYZE_PRINTF1 ("APPLE protocol detected\n");
irmp_protocol = IRMP_APPLE_PROTOCOL;
irmp_address = (irmp_command & 0xFF00) >> 8; // address was received in command!
irmp_command &= 0x00FF;
}
else
{
ANALYZE_PRINTF1 ("ONKYO protocol detected\n");
irmp_protocol = IRMP_ONKYO_PROTOCOL;
}
tReturnCode = TRUE;
break;
#endif
#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1
case IRMP_VINCENT_PROTOCOL:
if ((irmp_command >> 8) == (irmp_command & 0x00FF))
{
irmp_command &= 0xff;
tReturnCode = TRUE;
}
break;
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
case IRMP_KASEIKYO_PROTOCOL:
/*
* Todo AJ 14.7.22 The bit before the command (not existent bit 16 of command) is skipped and I have a Panasonic remote where it is 1 for 2 buttons
* and the 4 LSB command bits are always zero for this remote
*/
if( irmp_address == 0x2002) // PANASONIC_VENDOR_ID_CODE
{
ANALYZE_PRINTF1 ("Kaseikyo_Panasonic protocol detected\n");
irmp_protocol = IRMP_PANASONIC_PROTOCOL;
irmp_command = irmp_command >> 4; // remove the 4 zero bits
irmp_address = (irmp_command & 0xF00) >> 8; // LSB address (genre1) was received in command!
irmp_address |= irmp_flags & 0xF0; // MSB of address(genre2 bits) are located in MSB of the flag byte
irmp_command &= 0x00FF;
}
tReturnCode = TRUE;
break;
#endif
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1
case IRMP_BOSE_PROTOCOL:
if ((irmp_command >> 8) == (~irmp_command & 0x00FF))
{
irmp_command &= 0xff;
tReturnCode = TRUE;
}
break;
#endif
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
case IRMP_MERLIN_PROTOCOL:
if (irmp_bit == 10)
{
tReturnCode = TRUE;
}
else if (irmp_bit >= 19 && ((irmp_bit - 3) % 8 == 0))
{
if (((irmp_command >> 1) & 1) != (irmp_command & 1))
{
irmp_command >>= 1;
irmp_command |= ((irmp_address & 1) << (irmp_bit - 12));
irmp_address >>= 1;
tReturnCode = TRUE;
}
}
break;
#endif
#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1
case IRMP_SIEMENS_PROTOCOL:
case IRMP_RUWIDO_PROTOCOL:
if (((irmp_command >> 1) & 0x0001) == (~irmp_command & 0x0001))
{
irmp_command >>= 1;
tReturnCode = TRUE;
}
break;
#endif
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
case IRMP_KATHREIN_PROTOCOL:
if (irmp_command != 0x0000)
{
tReturnCode = TRUE;
}
break;
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
case IRMP_RC5_PROTOCOL:
irmp_address &= ~0x20; // clear toggle bit
tReturnCode = TRUE;
break;
#endif
#if IRMP_SUPPORT_S100_PROTOCOL == 1
case IRMP_S100_PROTOCOL:
irmp_address &= ~0x20; // clear toggle bit
tReturnCode = TRUE;
break;
#endif
#if IRMP_SUPPORT_IR60_PROTOCOL == 1
case IRMP_IR60_PROTOCOL:
if (irmp_command != 0x007d) // 0x007d (== 62<<1 + 1) is start instruction frame
{
tReturnCode = TRUE;
}
else
{
ANALYZE_PRINTF1("Info IR60: got start instruction frame\n");
}
break;
#endif
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
case IRMP_RCCAR_PROTOCOL:
// frame in irmp_data:
// Bit 12 11 10 9 8 7 6 5 4 3 2 1 0
// V D7 D6 D5 D4 D3 D2 D1 D0 A1 A0 C1 C0 // 10 9 8 7 6 5 4 3 2 1 0
irmp_address = (irmp_command & 0x000C) >> 2; // addr: 0 0 0 0 0 0 0 0 0 A1 A0
irmp_command = ((irmp_command & 0x1000) >> 2) | // V-Bit: V 0 0 0 0 0 0 0 0 0 0
((irmp_command & 0x0003) << 8) | // C-Bits: 0 C1 C0 0 0 0 0 0 0 0 0
((irmp_command & 0x0FF0) >> 4); // D-Bits: D7 D6 D5 D4 D3 D2 D1 D0
tReturnCode = TRUE; // Summe: V C1 C0 D7 D6 D5 D4 D3 D2 D1 D0
break;
#endif
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 // squeeze code to 8 bit, upper bit indicates release-key
case IRMP_NETBOX_PROTOCOL:
if (irmp_command & 0x1000) // last bit set?
{
if ((irmp_command & 0x1f) == 0x15) // key pressed: 101 01 (LSB)
{
irmp_command >>= 5;
irmp_command &= 0x7F;
tReturnCode = TRUE;
}
else if ((irmp_command & 0x1f) == 0x10) // key released: 000 01 (LSB)
{
irmp_command >>= 5;
irmp_command |= 0x80;
tReturnCode = TRUE;
}
else
{
ANALYZE_PRINTF1("error NETBOX: bit6/7 must be 0/1\n");
}
}
else
{
ANALYZE_PRINTF1("error NETBOX: last bit not set\n");
}
break;
#endif
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1
case IRMP_LEGO_PROTOCOL:
{
uint_fast8_t crc = 0x0F ^ ((irmp_command & 0xF000) >> 12) ^ ((irmp_command & 0x0F00) >> 8) ^ ((irmp_command & 0x00F0) >> 4);
if ((irmp_command & 0x000F) == crc)
{
irmp_command >>= 4;
tReturnCode = TRUE;
}
else
{
ANALYZE_PRINTF1 ("CRC error in LEGO protocol\n");
// rtc = TRUE; // don't accept codes with CRC errors
}
break;
}
#endif
#if IRMP_SUPPORT_METZ_PROTOCOL == 1
case IRMP_METZ_PROTOCOL:
irmp_address &= ~0x40; // clear toggle bit
if (((~irmp_address) & 0x07) == (irmp_address >> 3) && ((~irmp_command) & 0x3f) == (irmp_command >> 6))
{
irmp_address >>= 3;
irmp_command >>= 6;
tReturnCode = TRUE;
}
break;
#endif
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 || IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
case RF_X10_PROTOCOL:
case RF_MEDION_PROTOCOL:
{
uint8_t channel;
uint8_t checksum;
channel = irmp_command & 0x0F; // lower nibble: RF channel 0-15
irmp_command >>= 4; // shift out channel
checksum = irmp_address; // get checksum
if (((irmp_command + (0x0055 + (channel << 4))) & 0x7F) == checksum)
{ // checksum correct?
irmp_address = channel + 1; // set address to channel + 1
tReturnCode = TRUE;
}
break;
}
#endif
default:
{
tReturnCode = TRUE;
break;
}
}
if (tReturnCode)
{
irmp_data_p->protocol = irmp_protocol;
irmp_data_p->address = irmp_address;
irmp_data_p->command = irmp_command;
#if IRMP_AUTODETECT_REPEATRATE
tmp_delta = (pass_on_delta_detection * (1000000 / F_INTERRUPTS)) / 1000; // ms, this division is not precise
if (tmp_delta > 0xFF ) // reduce to uint8_t
delta = 0xFF;
else
delta = tmp_delta;
if (irmp_protocol != previous_irmp_protocol) { // reset
min_delta = 170;
upper_border = min_delta * (100 + JITTER_COMPENSATION) / 100 + 1;
timeout = 1;
keep_same_key = 0;
previous_irmp_protocol = irmp_protocol;
} else {
if (!(irmp_protocol == IRMP_NEC_PROTOCOL && delta < 75)) { // if NEC, ignore first short interval
if (delta < min_delta && same_key)
min_delta = delta;
}
upper_border = min_delta * (100 + JITTER_COMPENSATION) / 100 + 1;
timeout = (delta >= upper_border);
if (irmp_protocol == IRMP_RC5_PROTOCOL || irmp_protocol == IRMP_RC6_PROTOCOL || irmp_protocol == IRMP_RC6A_PROTOCOL || irmp_protocol == IRMP_RECS80_PROTOCOL \
|| irmp_protocol == IRMP_RECS80EXT_PROTOCOL || irmp_protocol == IRMP_RCMM24_PROTOCOL || irmp_protocol == IRMP_RCMM32_PROTOCOL \
|| irmp_protocol == IRMP_THOMSON_PROTOCOL || irmp_protocol == IRMP_S100_PROTOCOL || irmp_protocol == IRMP_METZ_PROTOCOL) {
if (same_key) // same_key is false, if toggle; not using timeout helps detecting repeats after misdetection and timeout isn't needed for discerning repetition
irmp_flags |= IRMP_FLAG_REPETITION;
} else {
if (same_key && !timeout)
irmp_flags |= IRMP_FLAG_REPETITION;
}
keep_same_key = same_key;
same_key = 0;
}
#endif
irmp_data_p->flags = irmp_flags;
}
else
{
irmp_protocol = IRMP_UNKNOWN_PROTOCOL;
}
irmp_command = 0; // don't reset irmp_protocol here, needed for detection of NEC & JVC repetition frames!
irmp_address = 0;
irmp_flags = 0;
irmp_ir_detected = FALSE;
}
return tReturnCode;
}
#if IRMP_USE_CALLBACK == 1
void
irmp_set_callback_ptr (void (*cb)(uint_fast8_t))
{
irmp_callback_ptr = cb;
}
#endif // IRMP_USE_CALLBACK == 1
// these statics must not be volatile, because they are only used by irmp_store_bit(), which is called by irmp_ISR()
static uint_fast16_t irmp_tmp_address; // ir address
#if IRMP_32_BIT == 1
static uint_fast32_t irmp_tmp_command; // ir command
#else
static uint_fast16_t irmp_tmp_command; // ir command
#endif
#if (IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)) || IRMP_SUPPORT_NEC42_PROTOCOL == 1
static uint_fast16_t irmp_tmp_address2; // ir address
static uint_fast16_t irmp_tmp_command2; // ir command
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
static uint_fast16_t irmp_lgair_address; // ir address
static uint_fast16_t irmp_lgair_command; // ir command
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
static uint_fast16_t irmp_melinera_command; // ir command
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
static uint_fast16_t irmp_tmp_id; // ir id (only SAMSUNG)
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
static uint8_t xor_check[6]; // check kaseikyo "parity" bits
static uint_fast8_t genre2; // save genre2 bits here, later copied to MSB in flags
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
static uint_fast8_t parity; // number of '1' of the first 14 bits, check if even.
#endif
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
static uint_fast8_t check; // number of '1' of the first 14 bits, check if even.
static uint_fast8_t mitsu_parity; // number of '1' of the first 14 bits, check if even.
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* store bit
* @details store bit in temp address or temp command
* @param value to store: 0 or 1
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// verhindert, dass irmp_store_bit() inline compiliert wird:
// static void irmp_store_bit (uint_fast8_t) __attribute__ ((noinline));
static void
irmp_store_bit (uint_fast8_t value)
{
#if IRMP_SUPPORT_ACP24_PROTOCOL == 1
if (irmp_param.protocol == IRMP_ACP24_PROTOCOL) // squeeze 64 bits into 16 bits:
{
if (value)
{
// ACP24-Frame:
// 1 2 3 4 5 6
// 0123456789012345678901234567890123456789012345678901234567890123456789
// N VVMMM ? ??? t vmA x y TTTT
//
// irmp_data_p->command:
//
// 5432109876543210
// NAVVvMMMmtxyTTTT
switch (irmp_bit)
{
case 0: irmp_tmp_command |= (1<<15); break; // N
case 2: irmp_tmp_command |= (1<<13); break; // V
case 3: irmp_tmp_command |= (1<<12); break; // V
case 4: irmp_tmp_command |= (1<<10); break; // M
case 5: irmp_tmp_command |= (1<< 9); break; // M
case 6: irmp_tmp_command |= (1<< 8); break; // M
case 20: irmp_tmp_command |= (1<< 6); break; // t
case 22: irmp_tmp_command |= (1<<11); break; // v
case 23: irmp_tmp_command |= (1<< 7); break; // m
case 24: irmp_tmp_command |= (1<<14); break; // A
case 26: irmp_tmp_command |= (1<< 5); break; // x
case 44: irmp_tmp_command |= (1<< 4); break; // y
case 66: irmp_tmp_command |= (1<< 3); break; // T
case 67: irmp_tmp_command |= (1<< 2); break; // T
case 68: irmp_tmp_command |= (1<< 1); break; // T
case 69: irmp_tmp_command |= (1<< 0); break; // T
}
}
}
else
#endif // IRMP_SUPPORT_ACP24_PROTOCOL
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL)
{
if (irmp_bit < 14)
{
if (value)
{
parity++;
}
}
else if (irmp_bit == 14)
{
if (value) // value == 1: even parity
{
if (parity & 0x01)
{
parity = PARITY_CHECK_FAILED;
}
else
{
parity = PARITY_CHECK_OK;
}
}
else
{
if (parity & 0x01) // value == 0: odd parity
{
parity = PARITY_CHECK_OK;
}
else
{
parity = PARITY_CHECK_FAILED;
}
}
}
}
else
#endif
{
;
}
#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1
if (irmp_bit == 0 && irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL)
{
first_bit = value;
}
else
#endif
if (irmp_bit >= irmp_param.address_offset && irmp_bit < irmp_param.address_end)
{
if (irmp_param.lsb_first)
{
irmp_tmp_address |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.address_offset)); // CV wants cast
}
else
{
irmp_tmp_address <<= 1;
irmp_tmp_address |= value;
}
}
else if (irmp_bit >= irmp_param.command_offset && irmp_bit < irmp_param.command_end)
{
if (irmp_param.lsb_first)
{
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit >= 32)
{
irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - 32)); // CV wants cast
}
else
#endif
{
irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.command_offset)); // CV wants cast
}
}
else
{
irmp_tmp_command <<= 1;
irmp_tmp_command |= value;
}
}
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL)
{
if (irmp_bit < 8)
{
irmp_lgair_address <<= 1; // LGAIR uses MSB
irmp_lgair_address |= value;
}
else if (irmp_bit < 24)
{
irmp_lgair_command <<= 1; // LGAIR uses MSB
irmp_lgair_command |= value;
}
}
// NO else!
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL || irmp_param.protocol == IRMP_MELINERA_PROTOCOL)
{
irmp_melinera_command <<= 1; // MELINERA uses MSB
irmp_melinera_command |= value;
}
#endif
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit >= 13 && irmp_bit < 26)
{
irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit - 13)); // CV wants cast
}
else
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit >= SAMSUNG_ID_OFFSET && irmp_bit < SAMSUNG_ID_OFFSET + SAMSUNG_ID_LEN)
{
irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - SAMSUNG_ID_OFFSET)); // store with LSB first
}
else
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL)
{
if (irmp_bit >= 20 && irmp_bit < 24)
{
irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - 8)); // store 4 system bits (genre 1) in upper nibble with LSB first
}
else if (irmp_bit >= 24 && irmp_bit < 28)
{
genre2 |= (((uint_fast8_t) (value)) << (irmp_bit - 20)); // store 4 system bits (genre 2) in upper nibble with LSB first
}
if (irmp_bit < KASEIKYO_COMPLETE_DATA_LEN)
{
if (value)
{
xor_check[irmp_bit / 8] |= 1 << (irmp_bit % 8);
}
else
{
xor_check[irmp_bit / 8] &= ~(1 << (irmp_bit % 8));
}
}
}
else
#endif
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL) // squeeze 64 bits into 16 bits:
{
if (irmp_bit == 72 )
{ // irmp_tmp_address, irmp_tmp_command received: check parity & compress
mitsu_parity = PARITY_CHECK_OK;
check = irmp_tmp_address >> 8; // inverted upper byte == lower byte?
check = ~ check;
if (check == (irmp_tmp_address & 0xFF))
{ // ok:
irmp_tmp_address <<= 8; // throw away upper byte
}
else
{
mitsu_parity = PARITY_CHECK_FAILED;
}
check = irmp_tmp_command >> 8; // inverted upper byte == lower byte?
check = ~ check;
if (check == (irmp_tmp_command & 0xFF))
{ // ok: pack together
irmp_tmp_address |= irmp_tmp_command & 0xFF; // byte 1, byte2 in irmp_tmp_address, irmp_tmp_command can be used for byte 3
}
else
{
mitsu_parity = PARITY_CHECK_FAILED;
}
irmp_tmp_command = 0;
}
if (irmp_bit >= 72 )
{ // receive 3. word in irmp_tmp_command
irmp_tmp_command <<= 1;
irmp_tmp_command |= value;
}
}
else
#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
{
;
}
irmp_bit++;
}
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* store bit
* @details store bit in temp address or temp command
* @param value to store: 0 or 1
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
static void
irmp_store_bit2 (uint_fast8_t value)
{
uint_fast8_t irmp_bit2;
if (irmp_param.protocol)
{
irmp_bit2 = irmp_bit - 2;
}
else
{
irmp_bit2 = irmp_bit - 1;
}
if (irmp_bit2 >= irmp_param2.address_offset && irmp_bit2 < irmp_param2.address_end)
{
irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.address_offset)); // CV wants cast
}
else if (irmp_bit2 >= irmp_param2.command_offset && irmp_bit2 < irmp_param2.command_end)
{
irmp_tmp_command2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.command_offset)); // CV wants cast
}
}
#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
#if defined(ANALYZE)
static uint32_t s_curSample = 0;
static uint32_t s_startBitSample = 0;
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ISR routine
* @details ISR routine, called 10000 to 20000 times per second
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
static uint_fast8_t irmp_start_bit_detected; // flag: start bit detected
static uint_fast8_t wait_for_space; // flag: wait for data bit space
static uint_fast8_t wait_for_start_space; // flag: wait for start bit space
#if __SIZEOF_INT__ == 4
static uint_fast16_t irmp_pulse_time; // count bit time for pulse
#else
static uint_fast8_t irmp_pulse_time; // count bit time for pulse
#endif
static PAUSE_LEN irmp_pause_time; // count bit time for pause
static uint_fast16_t key_repetition_len; // SIRCS repeats frame 2-5 times with 45 ms pause
static uint_fast8_t repetition_frame_number;
#if defined(ARDUINO)
#include "irmpArduinoExt.hpp" // Must be included after declaration of irmp_start_bit_detected etc.
#endif
/*
* 4 us idle, 45 us at start of each pulse @16 MHz ATmega 328p
*/
#if defined(ESP8266) || defined(ESP32)
bool IRAM_ATTR irmp_ISR(void)
#else
# ifdef __cplusplus
bool irmp_ISR(void)
# else
uint_fast8_t irmp_ISR(void)
# endif
#endif
{
static uint_fast16_t last_irmp_address = 0xFFFF; // save last irmp address to recognize key repetition
#if IRMP_ENABLE_RELEASE_DETECTION == 1
static uint_fast8_t key_released = TRUE;
#endif
#if IRMP_32_BIT == 1
static uint_fast32_t last_irmp_command = 0xFFFFFFFF; // save last irmp command to recognize key repetition
#else
static uint_fast16_t last_irmp_command = 0xFFFF; // save last irmp command to recognize key repetition
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
static uint_fast16_t last_irmp_denon_command; // save last irmp command to recognize DENON frame repetition
static uint_fast16_t denon_repetition_len = 0xFFFF; // denon repetition len of 2nd auto generated frame
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1
static uint_fast8_t rc5_cmd_bit6; // bit 6 of RC5 command is the inverted 2nd start bit
#endif
#if IRMP_SUPPORT_MANCHESTER == 1
static PAUSE_LEN last_pause; // last pause value
#endif
#if IRMP_SUPPORT_MANCHESTER == 1 || IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
static uint_fast8_t last_value; // last bit value
#endif
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
static uint_fast8_t waiting_for_2nd_pulse = 0;
#endif
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
uint_fast8_t bit_0 = 0;
#endif
uint_fast8_t irmp_input; // input value
#if defined(ANALYZE)
time_counter++;
#endif // ANALYZE
#if IRMP_HIGH_ACTIVE == 1
irmp_input = ! input(IRMP_PIN);
#else
irmp_input = input(IRMP_PIN);
#endif
#if IRMP_USE_CALLBACK == 1
if (irmp_callback_ptr)
{
static uint_fast8_t last_inverted_input;
if (last_inverted_input != !irmp_input)
{
(*irmp_callback_ptr) (! irmp_input);
last_inverted_input = !irmp_input;
}
}
#endif // IRMP_USE_CALLBACK == 1
#if defined(ARDUINO)
# if !defined(NO_LED_FEEDBACK_CODE)
irmp_DoLEDFeedback(irmp_input);
# endif
#endif
irmp_log(irmp_input); // log ir signal, if IRMP_LOGGING defined
#if IRMP_AUTODETECT_REPEATRATE
if (delta_detection < 0xFFFF)
delta_detection++;
#if IRMP_ENABLE_RELEASE_DETECTION == 1
if (! key_released && delta_detection * (1000000 / F_INTERRUPTS) / 1000 >= upper_border)
{
irmp_address = last_irmp_address;
irmp_command = last_irmp_command;
irmp_flags = IRMP_FLAG_RELEASE;
irmp_ir_detected = TRUE;
key_released = TRUE;
}
#endif
#endif
if (! irmp_ir_detected) // ir code already detected?
{ // no...
if (! irmp_start_bit_detected) // start bit detected?
{ // no...
if (! irmp_input) // receiving burst?
{ // yes...
// irmp_busy_flag = TRUE;
#if defined(ANALYZE)
if (! irmp_pulse_time)
{
s_startBitSample = s_curSample;
ANALYZE_PRINTF2("%8.3fms [starting pulse]\n", (double) (time_counter * 1000) / F_INTERRUPTS);
}
#endif // ANALYZE
irmp_pulse_time++; // increment counter
}
else
{ // no...
if (irmp_pulse_time) // it's dark....
{ // set flags for counting the time of darkness...
irmp_start_bit_detected = 1;
wait_for_start_space = 1;
wait_for_space = 0;
irmp_tmp_command = 0;
irmp_tmp_address = 0;
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
genre2 = 0;
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
irmp_tmp_id = 0;
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1
irmp_tmp_command2 = 0;
irmp_tmp_address2 = 0;
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
irmp_lgair_command = 0;
irmp_lgair_address = 0;
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
irmp_melinera_command = 0;
#endif
irmp_bit = 0xff;
irmp_pause_time = 1; // 1st pause: set to 1, not to 0!
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1
rc5_cmd_bit6 = 0; // fm 2010-03-07: bugfix: reset it after incomplete RC5 frame!
#endif
}
else
{
if (key_repetition_len < 0xFFFF) // avoid overflow of counter
{
key_repetition_len++;
#if IRMP_ENABLE_RELEASE_DETECTION == 1
#if !IRMP_AUTODETECT_REPEATRATE
if (! key_released && key_repetition_len > IRMP_KEY_RELEASE_LEN)
{
irmp_address = last_irmp_address;
irmp_command = last_irmp_command;
irmp_flags = IRMP_FLAG_RELEASE;
irmp_ir_detected = TRUE;
key_released = TRUE;
}
#endif
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
if (denon_repetition_len < 0xFFFF) // avoid overflow of counter
{
denon_repetition_len++;
if (denon_repetition_len >= DENON_AUTO_REPETITION_PAUSE_LEN && last_irmp_denon_command != 0)
{
ANALYZE_PRINTF2 ("%8.3fms warning: did not receive inverted command repetition\n",
(double) (time_counter * 1000) / F_INTERRUPTS);
last_irmp_denon_command = 0;
denon_repetition_len = 0xFFFF;
}
}
#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1
}
}
}
}
else
{
if (wait_for_start_space) // we have received start bit...
{ // ...and are counting the time of darkness
if (irmp_input) // still dark?
{ // yes
irmp_pause_time++; // increment counter
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
if (((irmp_pulse_time < NIKON_START_BIT_PULSE_LEN_MIN || irmp_pulse_time > NIKON_START_BIT_PULSE_LEN_MAX) && irmp_pause_time > IRMP_TIMEOUT_LEN) ||
irmp_pause_time > IRMP_TIMEOUT_NIKON_LEN)
#else
if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout?
#endif
{ // yes...
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
if (irmp_protocol == IRMP_JVC_PROTOCOL) // don't show eror if JVC protocol, irmp_pulse_time has been set below!
{
;
}
else
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
{
ANALYZE_PRINTF4 ("%8.3fms error 1: pause after start bit pulse %d too long: %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
}
irmp_start_bit_detected = 0; // reset flags, let's wait for another start bit
irmp_pulse_time = 0;
irmp_pause_time = 0;
}
}
else
{ // receiving first data pulse!
IRMP_PARAMETER * irmp_param_p;
irmp_param_p = (IRMP_PARAMETER *) 0;
irmp_bit = 0;
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
irmp_param2.protocol = 0;
#endif
ANALYZE_PRINTF4 ("%8.3fms [start-bit: pulse = %2d, pause = %2d]\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time);
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
if (irmp_pulse_time >= SIRCS_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIRCS_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= SIRCS_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIRCS_START_BIT_PAUSE_LEN_MAX)
{ // it's SIRCS
ANALYZE_PRINTF5 ("protocol = SIRCS, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX,
SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &sircs_param;
}
else
#endif // IRMP_SUPPORT_SIRCS_PROTOCOL == 1
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame
irmp_pulse_time >= JVC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= JVC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= JVC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= JVC_REPEAT_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = NEC or JVC (type 1) repeat frame, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
JVC_START_BIT_PULSE_LEN_MIN, JVC_START_BIT_PULSE_LEN_MAX,
JVC_REPEAT_START_BIT_PAUSE_LEN_MIN, JVC_REPEAT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec_param;
}
else
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX)
{
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
ANALYZE_PRINTF5 ("protocol = NEC42, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX,
NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec42_param;
#else
ANALYZE_PRINTF5 ("protocol = NEC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX,
NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec_param;
#endif
}
else if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NEC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_REPEAT_START_BIT_PAUSE_LEN_MAX)
{ // it's NEC
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
if (irmp_protocol == IRMP_JVC_PROTOCOL) // last protocol was JVC, awaiting repeat frame
{ // some jvc remote controls use nec repetition frame for jvc repetition frame
ANALYZE_PRINTF5 ("protocol = JVC repeat frame type 2, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX,
NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec_param;
}
else
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
{
ANALYZE_PRINTF5 ("protocol = NEC (repetition frame), start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX,
NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec_rep_param;
}
}
else
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame
irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NEC_0_PAUSE_LEN_MIN && irmp_pause_time <= NEC_0_PAUSE_LEN_MAX)
{ // it's JVC repetition type 3
ANALYZE_PRINTF5 ("protocol = JVC repeat frame type 3, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX,
NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nec_param;
}
else
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1
#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
if (irmp_pulse_time >= TELEFUNKEN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= TELEFUNKEN_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= TELEFUNKEN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= TELEFUNKEN_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = TELEFUNKEN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
TELEFUNKEN_START_BIT_PULSE_LEN_MIN, TELEFUNKEN_START_BIT_PULSE_LEN_MAX,
TELEFUNKEN_START_BIT_PAUSE_LEN_MIN, TELEFUNKEN_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &telefunken_param;
}
else
#endif // IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
if (irmp_pulse_time >= ROOMBA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= ROOMBA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ROOMBA_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = ROOMBA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
ROOMBA_START_BIT_PULSE_LEN_MIN, ROOMBA_START_BIT_PULSE_LEN_MAX,
ROOMBA_START_BIT_PAUSE_LEN_MIN, ROOMBA_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &roomba_param;
}
else
#endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
#if IRMP_SUPPORT_ACP24_PROTOCOL == 1
if (irmp_pulse_time >= ACP24_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ACP24_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= ACP24_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ACP24_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = ACP24, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
ACP24_START_BIT_PULSE_LEN_MIN, ACP24_START_BIT_PULSE_LEN_MAX,
ACP24_START_BIT_PAUSE_LEN_MIN, ACP24_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &acp24_param;
}
else
#endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1
if (irmp_pulse_time >= PENTAX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PENTAX_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= PENTAX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PENTAX_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = PENTAX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
PENTAX_START_BIT_PULSE_LEN_MIN, PENTAX_START_BIT_PULSE_LEN_MAX,
PENTAX_START_BIT_PAUSE_LEN_MIN, PENTAX_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &pentax_param;
}
else
#endif // IRMP_SUPPORT_PENTAX_PROTOCOL == 1
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
if (irmp_pulse_time >= NIKON_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NIKON_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NIKON_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NIKON_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = NIKON, start bit timings: pulse: %3d - %3d, pause: %3u - %3u\n",
NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX,
(unsigned int) NIKON_START_BIT_PAUSE_LEN_MIN, (unsigned int) NIKON_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nikon_param;
}
else
#endif // IRMP_SUPPORT_NIKON_PROTOCOL == 1
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
if (irmp_pulse_time >= SAMSUNG_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX)
{ // it's SAMSUNG
ANALYZE_PRINTF5 ("protocol = SAMSUNG, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX,
SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &samsung_param;
}
else
#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1
if (irmp_pulse_time >= SAMSUNGAH_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNGAH_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= SAMSUNGAH_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNGAH_START_BIT_PAUSE_LEN_MAX)
{ // it's SAMSUNGAH
ANALYZE_PRINTF5 ("protocol = SAMSUNGAH, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
SAMSUNGAH_START_BIT_PULSE_LEN_MIN, SAMSUNGAH_START_BIT_PULSE_LEN_MAX,
SAMSUNGAH_START_BIT_PAUSE_LEN_MIN, SAMSUNGAH_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &samsungah_param;
}
else
#endif // IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1
#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1
if (irmp_pulse_time >= MATSUSHITA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MATSUSHITA_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= MATSUSHITA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MATSUSHITA_START_BIT_PAUSE_LEN_MAX)
{ // it's MATSUSHITA
ANALYZE_PRINTF5 ("protocol = MATSUSHITA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX,
MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &matsushita_param;
}
else
#endif // IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
if (irmp_pulse_time >= KASEIKYO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KASEIKYO_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= KASEIKYO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KASEIKYO_START_BIT_PAUSE_LEN_MAX)
{ // it's KASEIKYO
ANALYZE_PRINTF5 ("protocol = KASEIKYO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX,
KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &kaseikyo_param;
}
else
#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1
if (irmp_pulse_time >= PANASONIC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PANASONIC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= PANASONIC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PANASONIC_START_BIT_PAUSE_LEN_MAX)
{ // it's PANASONIC
ANALYZE_PRINTF5 ("protocol = PANASONIC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
PANASONIC_START_BIT_PULSE_LEN_MIN, PANASONIC_START_BIT_PULSE_LEN_MAX,
PANASONIC_START_BIT_PAUSE_LEN_MIN, PANASONIC_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &panasonic_param;
}
else
#endif // IRMP_SUPPORT_PANASONIC_PROTOCOL == 1
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
if (irmp_pulse_time >= MITSU_HEAVY_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MITSU_HEAVY_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX)
{ // it's MITSU_HEAVY
ANALYZE_PRINTF5 ("protocol = MITSU_HEAVY, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
MITSU_HEAVY_START_BIT_PULSE_LEN_MIN, MITSU_HEAVY_START_BIT_PULSE_LEN_MAX,
MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN, MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &mitsu_heavy_param;
}
else
#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1
if (irmp_pulse_time >= VINCENT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= VINCENT_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= VINCENT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= VINCENT_START_BIT_PAUSE_LEN_MAX)
{ // it's VINCENT
ANALYZE_PRINTF5 ("protocol = VINCENT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
VINCENT_START_BIT_PULSE_LEN_MIN, VINCENT_START_BIT_PULSE_LEN_MAX,
VINCENT_START_BIT_PAUSE_LEN_MIN, VINCENT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &vincent_param;
}
else
#endif // IRMP_SUPPORT_VINCENT_PROTOCOL == 1
#if IRMP_SUPPORT_METZ_PROTOCOL == 1
if (irmp_pulse_time >= METZ_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= METZ_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= METZ_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= METZ_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = METZ, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
METZ_START_BIT_PULSE_LEN_MIN, METZ_START_BIT_PULSE_LEN_MAX,
METZ_START_BIT_PAUSE_LEN_MIN, METZ_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &metz_param;
}
else
#endif // IRMP_SUPPORT_METZ_PROTOCOL == 1
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 // RF_GEN24 has no start bit
if (irmp_pulse_time >= RF_GEN24_0_PULSE_LEN_MIN && irmp_pulse_time <= RF_GEN24_0_PULSE_LEN_MAX &&
irmp_pause_time >= RF_GEN24_0_PAUSE_LEN_MIN && irmp_pause_time <= RF_GEN24_0_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("protocol = RF_GEN24\n");
irmp_param_p = (IRMP_PARAMETER *) &rf_gen24_param;
bit_0 = 0;
}
else
if (irmp_pulse_time >= RF_GEN24_1_PULSE_LEN_MIN && irmp_pulse_time <= RF_GEN24_1_PULSE_LEN_MAX &&
irmp_pause_time >= RF_GEN24_1_PAUSE_LEN_MIN && irmp_pause_time <= RF_GEN24_1_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("protocol = RF_GEN24\n");
irmp_param_p = (IRMP_PARAMETER *) &rf_gen24_param;
bit_0 = 1;
}
else
#endif // IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1
if (irmp_pulse_time >= RF_X10_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RF_X10_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RF_X10_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RF_X10_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = RF_X10, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RF_X10_START_BIT_PULSE_LEN_MIN, RF_X10_START_BIT_PULSE_LEN_MAX,
RF_X10_START_BIT_PAUSE_LEN_MIN, RF_X10_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &rf_x10_param;
}
else
#endif // IRMP_SUPPORT_RF_X10_PROTOCOL == 1
#if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
if (irmp_pulse_time >= RF_MEDION_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RF_MEDION_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RF_MEDION_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RF_MEDION_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = RF_MEDION, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RF_MEDION_START_BIT_PULSE_LEN_MIN, RF_MEDION_START_BIT_PULSE_LEN_MAX,
RF_MEDION_START_BIT_PAUSE_LEN_MIN, RF_MEDION_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &rf_medion_param;
}
else
#endif // IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
#if IRMP_SUPPORT_RECS80_PROTOCOL == 1
if (irmp_pulse_time >= RECS80_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RECS80_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80_START_BIT_PAUSE_LEN_MAX)
{ // it's RECS80
ANALYZE_PRINTF5 ("protocol = RECS80, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX,
RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &recs80_param;
}
else
#endif // IRMP_SUPPORT_RECS80_PROTOCOL == 1
#if IRMP_SUPPORT_S100_PROTOCOL == 1
if (((irmp_pulse_time >= S100_START_BIT_LEN_MIN && irmp_pulse_time <= S100_START_BIT_LEN_MAX) ||
(irmp_pulse_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX)) &&
((irmp_pause_time >= S100_START_BIT_LEN_MIN && irmp_pause_time <= S100_START_BIT_LEN_MAX) ||
(irmp_pause_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX)))
{ // it's S100
ANALYZE_PRINTF9 ("protocol = S100, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n",
S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX,
2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX,
S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX,
2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &s100_param;
last_pause = irmp_pause_time;
if ((irmp_pulse_time > S100_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX) ||
(irmp_pause_time > S100_START_BIT_LEN_MAX && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX))
{
last_value = 0;
rc5_cmd_bit6 = 1<<6;
}
else
{
last_value = 1;
}
}
else
#endif // IRMP_SUPPORT_S100_PROTOCOL == 1
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
if (((irmp_pulse_time >= RC5_START_BIT_LEN_MIN && irmp_pulse_time <= RC5_START_BIT_LEN_MAX) ||
(irmp_pulse_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX)) &&
((irmp_pause_time >= RC5_START_BIT_LEN_MIN && irmp_pause_time <= RC5_START_BIT_LEN_MAX) ||
(irmp_pause_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)))
{ // it's RC5
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("protocol = RC5 or FDC\n");
ANALYZE_PRINTF5 ("FDC start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX,
FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX);
ANALYZE_PRINTF5 ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX,
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX);
memcpy_P (&irmp_param2, &fdc_param, sizeof (IRMP_PARAMETER));
}
else
#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("protocol = RC5 or RCCAR\n");
ANALYZE_PRINTF5 ("RCCAR start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX,
RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX);
ANALYZE_PRINTF5 ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX,
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX);
memcpy_P (&irmp_param2, &rccar_param, sizeof (IRMP_PARAMETER));
}
else
#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1
{
ANALYZE_PRINTF9 ("protocol = RC5, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n",
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX,
2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX,
RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX,
2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX);
}
irmp_param_p = (IRMP_PARAMETER *) &rc5_param;
last_pause = irmp_pause_time;
if ((irmp_pulse_time > RC5_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX) ||
(irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX))
{
last_value = 0;
rc5_cmd_bit6 = 1<<6;
}
else
{
last_value = 1;
}
}
else
#endif // IRMP_SUPPORT_RC5_PROTOCOL == 1
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
if ((irmp_pulse_time >= RCII_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCII_START_BIT_PULSE_LEN_MAX) &&
(irmp_pause_time >= RCII_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCII_START_BIT_PAUSE_LEN_MAX))
{ // it's RCII
ANALYZE_PRINTF5 ("protocol = RCII, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RCII_START_BIT_PULSE_LEN_MIN, RCII_START_BIT_PULSE_LEN_MAX,
RCII_START_BIT_PAUSE_LEN_MIN, RCII_START_BIT_PAUSE_LEN_MAX)
irmp_param_p = (IRMP_PARAMETER *) &rcii_param;
last_pause = irmp_pause_time;
waiting_for_2nd_pulse = 1;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_RCII_PROTOCOL == 1
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
if ( (irmp_pulse_time >= DENON_PULSE_LEN_MIN && irmp_pulse_time <= DENON_PULSE_LEN_MAX) &&
((irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) ||
(irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX)))
{ // it's DENON
ANALYZE_PRINTF7 ("protocol = DENON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n",
DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX,
DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX,
DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &denon_param;
}
else
#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1
#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1
if ( (irmp_pulse_time >= THOMSON_PULSE_LEN_MIN && irmp_pulse_time <= THOMSON_PULSE_LEN_MAX) &&
((irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) ||
(irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX)))
{ // it's THOMSON
ANALYZE_PRINTF7 ("protocol = THOMSON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n",
THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX,
THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX,
THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &thomson_param;
}
else
#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1
if (irmp_pulse_time >= BOSE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= BOSE_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= BOSE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BOSE_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = BOSE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
BOSE_START_BIT_PULSE_LEN_MIN, BOSE_START_BIT_PULSE_LEN_MAX,
BOSE_START_BIT_PAUSE_LEN_MIN, BOSE_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &bose_param;
}
else
#endif // IRMP_SUPPORT_BOSE_PROTOCOL == 1
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_pulse_time >= RC6_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RC6_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RC6_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RC6_START_BIT_PAUSE_LEN_MAX)
{ // it's RC6
ANALYZE_PRINTF5 ("protocol = RC6, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX,
RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &rc6_param;
last_pause = 0;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1
#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1
if (irmp_pulse_time >= RECS80EXT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80EXT_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RECS80EXT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80EXT_START_BIT_PAUSE_LEN_MAX)
{ // it's RECS80EXT
ANALYZE_PRINTF5 ("protocol = RECS80EXT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX,
RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &recs80ext_param;
}
else
#endif // IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1
if (irmp_pulse_time >= NUBERT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NUBERT_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NUBERT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NUBERT_START_BIT_PAUSE_LEN_MAX)
{ // it's NUBERT
ANALYZE_PRINTF5 ("protocol = NUBERT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX,
NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &nubert_param;
}
else
#endif // IRMP_SUPPORT_NUBERT_PROTOCOL == 1
#if IRMP_SUPPORT_FAN_PROTOCOL == 1
if (irmp_pulse_time >= FAN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FAN_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= FAN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FAN_START_BIT_PAUSE_LEN_MAX)
{ // it's FAN
ANALYZE_PRINTF5 ("protocol = FAN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
FAN_START_BIT_PULSE_LEN_MIN, FAN_START_BIT_PULSE_LEN_MAX,
FAN_START_BIT_PAUSE_LEN_MIN, FAN_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &fan_param;
}
else
#endif // IRMP_SUPPORT_FAN_PROTOCOL == 1
#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
if (irmp_pulse_time >= SPEAKER_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SPEAKER_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= SPEAKER_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SPEAKER_START_BIT_PAUSE_LEN_MAX)
{ // it's SPEAKER
ANALYZE_PRINTF5 ("protocol = SPEAKER, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
SPEAKER_START_BIT_PULSE_LEN_MIN, SPEAKER_START_BIT_PULSE_LEN_MAX,
SPEAKER_START_BIT_PAUSE_LEN_MIN, SPEAKER_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &speaker_param;
}
else
#endif // IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
if (irmp_pulse_time >= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX &&
irmp_pause_time >= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX)
{ // it's BANG_OLUFSEN
ANALYZE_PRINTF1 ("protocol = BANG_OLUFSEN\n");
ANALYZE_PRINTF5 ("start bit 1 timings: pulse: %3d - %3d, pause: %3d - %3d\n",
BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX,
BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX);
ANALYZE_PRINTF5 ("start bit 2 timings: pulse: %3d - %3d, pause: %3d - %3d\n",
BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX,
BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX);
ANALYZE_PRINTF5 ("start bit 3 timings: pulse: %3d - %3d, pause: %3d - %3d\n",
BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX,
BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX);
ANALYZE_PRINTF5 ("start bit 4 timings: pulse: %3d - %3d, pause: %3d - %3d\n",
BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX,
BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &bang_olufsen_param;
last_value = 0;
}
else
#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1
if (irmp_pulse_time >= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX &&
irmp_pause_time >= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX)
{ // it's GRUNDIG
ANALYZE_PRINTF5 ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX,
GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &grundig_param;
last_pause = irmp_pause_time;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 // check MERLIN before RUWIDO!
if (irmp_pulse_time >= MERLIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MERLIN_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= MERLIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MERLIN_START_BIT_PAUSE_LEN_MAX)
{ // it's MERLIN
ANALYZE_PRINTF5 ("protocol = MERLIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
MERLIN_START_BIT_PULSE_LEN_MIN, MERLIN_START_BIT_PULSE_LEN_MAX,
MERLIN_START_BIT_PAUSE_LEN_MIN, MERLIN_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &merlin_param;
last_pause = irmp_pause_time;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_MERLIN_PROTOCOL == 1
#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1
if (((irmp_pulse_time >= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX) ||
(irmp_pulse_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX)) &&
((irmp_pause_time >= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX) ||
(irmp_pause_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX)))
{ // it's RUWIDO or SIEMENS
ANALYZE_PRINTF9 ("protocol = RUWIDO, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n",
SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX,
2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX,
SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX,
2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &ruwido_param;
last_pause = irmp_pause_time;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = FDC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX,
FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &fdc_param;
}
else
#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = RCCAR, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX,
RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &rccar_param;
}
else
#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
if (irmp_pulse_time >= KATHREIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX)
{ // it's KATHREIN
ANALYZE_PRINTF5 ("protocol = KATHREIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
KATHREIN_START_BIT_PULSE_LEN_MIN, KATHREIN_START_BIT_PULSE_LEN_MAX,
KATHREIN_START_BIT_PAUSE_LEN_MIN, KATHREIN_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &kathrein_param;
}
else
#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1
if (irmp_pulse_time >= NETBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NETBOX_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= NETBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NETBOX_START_BIT_PAUSE_LEN_MAX)
{ // it's NETBOX
ANALYZE_PRINTF5 ("protocol = NETBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
NETBOX_START_BIT_PULSE_LEN_MIN, NETBOX_START_BIT_PULSE_LEN_MAX,
NETBOX_START_BIT_PAUSE_LEN_MIN, NETBOX_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &netbox_param;
}
else
#endif // IRMP_SUPPORT_NETBOX_PROTOCOL == 1
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1
if (irmp_pulse_time >= LEGO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= LEGO_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= LEGO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= LEGO_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = LEGO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX,
LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &lego_param;
}
else
#endif // IRMP_SUPPORT_LEGO_PROTOCOL == 1
#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1
if (irmp_pulse_time >= IRMP16_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= IRMP16_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= IRMP16_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= IRMP16_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = IRMP16, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
IRMP16_START_BIT_PULSE_LEN_MIN, IRMP16_START_BIT_PULSE_LEN_MAX,
IRMP16_START_BIT_PAUSE_LEN_MIN, IRMP16_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &irmp16_param;
}
else
#endif // IRMP_SUPPORT_IRMP16_PROTOCOL == 1
#if IRMP_SUPPORT_GREE_PROTOCOL == 1
if (irmp_pulse_time >= GREE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= GREE_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= GREE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= GREE_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF5 ("protocol = GREE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
GREE_START_BIT_PULSE_LEN_MIN, GREE_START_BIT_PULSE_LEN_MAX,
GREE_START_BIT_PAUSE_LEN_MIN, GREE_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &gree_param;
}
else
#endif // IRMP_SUPPORT_GREE_PROTOCOL == 1
#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1
if (irmp_pulse_time >= A1TVBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= A1TVBOX_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= A1TVBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= A1TVBOX_START_BIT_PAUSE_LEN_MAX)
{ // it's A1TVBOX
ANALYZE_PRINTF5 ("protocol = A1TVBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
A1TVBOX_START_BIT_PULSE_LEN_MIN, A1TVBOX_START_BIT_PULSE_LEN_MAX,
A1TVBOX_START_BIT_PAUSE_LEN_MIN, A1TVBOX_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &a1tvbox_param;
last_pause = 0;
last_value = 1;
}
else
#endif // IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
if (irmp_pulse_time >= ORTEK_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ORTEK_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= ORTEK_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ORTEK_START_BIT_PAUSE_LEN_MAX)
{ // it's ORTEK (Hama)
ANALYZE_PRINTF5 ("protocol = ORTEK, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
ORTEK_START_BIT_PULSE_LEN_MIN, ORTEK_START_BIT_PULSE_LEN_MAX,
ORTEK_START_BIT_PAUSE_LEN_MIN, ORTEK_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &ortek_param;
last_pause = 0;
last_value = 1;
parity = 0;
}
else
#endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
if (irmp_pulse_time >= RCMM32_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCMM32_START_BIT_PULSE_LEN_MAX &&
irmp_pause_time >= RCMM32_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_START_BIT_PAUSE_LEN_MAX)
{ // it's RCMM
ANALYZE_PRINTF5 ("protocol = RCMM, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n",
RCMM32_START_BIT_PULSE_LEN_MIN, RCMM32_START_BIT_PULSE_LEN_MAX,
RCMM32_START_BIT_PAUSE_LEN_MIN, RCMM32_START_BIT_PAUSE_LEN_MAX);
irmp_param_p = (IRMP_PARAMETER *) &rcmm_param;
}
else
#endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1
{
ANALYZE_PRINTF1 ("protocol = UNKNOWN\n");
irmp_start_bit_detected = 0; // wait for another start bit...
irmp_param.protocol = 0; // reset protocol
}
if (irmp_start_bit_detected)
{
memcpy_P (&irmp_param, irmp_param_p, sizeof (IRMP_PARAMETER));
if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER))
{
ANALYZE_PRINTF3 ("pulse_1: %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max);
ANALYZE_PRINTF3 ("pause_1: %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max);
}
else
{
ANALYZE_PRINTF5 ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max,
2 * irmp_param.pulse_1_len_min, 2 * irmp_param.pulse_1_len_max);
ANALYZE_PRINTF5 ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max,
2 * irmp_param.pause_1_len_min, 2 * irmp_param.pause_1_len_max);
}
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
if (irmp_param2.protocol)
{
ANALYZE_PRINTF3 ("pulse_0: %3d - %3d\n", irmp_param2.pulse_0_len_min, irmp_param2.pulse_0_len_max);
ANALYZE_PRINTF3 ("pause_0: %3d - %3d\n", irmp_param2.pause_0_len_min, irmp_param2.pause_0_len_max);
ANALYZE_PRINTF3 ("pulse_1: %3d - %3d\n", irmp_param2.pulse_1_len_min, irmp_param2.pulse_1_len_max);
ANALYZE_PRINTF3 ("pause_1: %3d - %3d\n", irmp_param2.pause_1_len_min, irmp_param2.pause_1_len_max);
}
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC6_PROTOCOL)
{
ANALYZE_PRINTF3 ("pulse_toggle: %3d - %3d\n", RC6_TOGGLE_BIT_LEN_MIN, RC6_TOGGLE_BIT_LEN_MAX);
}
#endif
if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER))
{
ANALYZE_PRINTF3 ("pulse_0: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max);
ANALYZE_PRINTF3 ("pause_0: %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max);
}
else
{
ANALYZE_PRINTF5 ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max,
2 * irmp_param.pulse_0_len_min, 2 * irmp_param.pulse_0_len_max);
ANALYZE_PRINTF5 ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max,
2 * irmp_param.pause_0_len_min, 2 * irmp_param.pause_0_len_max);
}
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL)
{
ANALYZE_PRINTF3 ("pulse_r: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max);
ANALYZE_PRINTF3 ("pause_r: %3d - %3d\n", BANG_OLUFSEN_R_PAUSE_LEN_MIN, BANG_OLUFSEN_R_PAUSE_LEN_MAX);
}
#endif
ANALYZE_PRINTF2 ("command_offset: %2d\n", irmp_param.command_offset);
ANALYZE_PRINTF2 ("command_len: %3d\n", irmp_param.command_end - irmp_param.command_offset);
ANALYZE_PRINTF2 ("complete_len: %3d\n", irmp_param.complete_len);
ANALYZE_PRINTF2 ("stop_bit: %3d\n", irmp_param.stop_bit);
}
#if IRMP_SUPPORT_MANCHESTER == 1
if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) &&
irmp_param.protocol != IRMP_RUWIDO_PROTOCOL && // Manchester, but not RUWIDO
irmp_param.protocol != IRMP_RC6_PROTOCOL /*** && // Manchester, but not RC6
irmp_param.protocol != IRMP_RCII_PROTOCOL ****/) // Manchester, but not RCII
{
if (irmp_pause_time > irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pulse_1_len_max)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1');
ANALYZE_NEWLINE ();
irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1);
}
else if (! last_value) // && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0');
ANALYZE_NEWLINE ();
irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0);
}
}
else
#endif // IRMP_SUPPORT_MANCHESTER == 1
#if IRMP_SUPPORT_SERIAL == 1
if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL)
{
; // do nothing
}
else
#endif // IRMP_SUPPORT_SERIAL == 1
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
if (irmp_param.protocol == IRMP_DENON_PROTOCOL)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX)
{ // pause timings correct for "1"?
ANALYZE_PUTCHAR ('1'); // yes, store 1
ANALYZE_NEWLINE ();
irmp_store_bit (1);
}
else // if (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX)
{ // pause timings correct for "0"?
ANALYZE_PUTCHAR ('0'); // yes, store 0
ANALYZE_NEWLINE ();
irmp_store_bit (0);
}
}
else
#endif // IRMP_SUPPORT_DENON_PROTOCOL == 1
#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1
if (irmp_param.protocol == IRMP_THOMSON_PROTOCOL)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
if (irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX)
{ // pause timings correct for "1"?
ANALYZE_PUTCHAR ('1'); // yes, store 1
ANALYZE_NEWLINE ();
irmp_store_bit (1);
}
else // if (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX)
{ // pause timings correct for "0"?
ANALYZE_PUTCHAR ('0'); // yes, store 0
ANALYZE_NEWLINE ();
irmp_store_bit (0);
}
}
else
#endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
if (irmp_param.protocol == RF_GEN24_PROTOCOL)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_PUTCHAR (bit_0 + '0');
ANALYZE_NEWLINE ();
irmp_store_bit (bit_0); // start bit is data bit
}
else
#endif // IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
{
; // else do nothing
}
irmp_pulse_time = 1; // set counter to 1, not 0
irmp_pause_time = 0;
wait_for_start_space = 0;
}
}
else if (wait_for_space) // the data section....
{ // counting the time of darkness....
uint_fast8_t got_light = FALSE;
if (irmp_input) // still dark?
{ // yes...
irmp_pause_time++; // increment counter
if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1 && irmp_pause_time > ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) ? 0 : STOP_BIT_PAUSE_LEN_MIN))
{
if (
#if IRMP_SUPPORT_MANCHESTER == 1
(irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) ||
#endif
#if IRMP_SUPPORT_SERIAL == 1
(irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) ||
#endif
(irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max))
{
if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER))
{
ANALYZE_PRINTF1 ("stop bit detected\n");
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
if (irmp_param.protocol == IRMP_MELINERA_PROTOCOL)
{
irmp_tmp_command = irmp_melinera_command; // set command
irmp_tmp_address = 0; // no address
}
#endif
}
irmp_param.stop_bit = 0;
}
else
{
ANALYZE_PRINTF5 ("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n",
irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max);
irmp_start_bit_detected = 0; // wait for another start bit...
irmp_pulse_time = 0;
irmp_pause_time = 0;
}
}
else
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && // Sony has a variable number of bits:
irmp_pause_time > SIRCS_PAUSE_LEN_MAX && // minimum is 12
irmp_bit >= 12 - 1) // pause too long?
{ // yes, break and close this frame
irmp_param.complete_len = irmp_bit + 1; // set new complete length
got_light = TRUE; // this is a lie, but helps (generates stop bit)
irmp_tmp_address |= (irmp_bit - SIRCS_MINIMUM_DATA_LEN + 1) << 8; // new: store number of additional bits in upper byte of address!
irmp_param.command_end = irmp_param.command_offset + irmp_bit + 1; // correct command length
irmp_pause_time = SIRCS_PAUSE_LEN_MAX - 1; // correct pause length
}
else
#endif
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
if (irmp_param.protocol == IRMP_MERLIN_PROTOCOL && // Merlin has a variable number of bits:
irmp_pause_time > MERLIN_START_BIT_PAUSE_LEN_MAX && // minimum is 8
irmp_bit >= 8 - 1) // pause too long?
{ // yes, break and close this frame
irmp_param.complete_len = irmp_bit; // set new complete length
got_light = TRUE; // this is a lie, but helps (generates stop bit)
irmp_pause_time = MERLIN_BIT_PAUSE_LEN_MAX - 1; // correct pause length
}
else
#endif
#if IRMP_SUPPORT_FAN_PROTOCOL == 1
if (irmp_param.protocol == IRMP_FAN_PROTOCOL && // FAN has no stop bit.
irmp_bit >= FAN_COMPLETE_DATA_LEN - 1) // last bit in frame
{ // yes, break and close this frame
if (irmp_pulse_time <= FAN_0_PULSE_LEN_MAX && irmp_pause_time >= FAN_0_PAUSE_LEN_MIN)
{
ANALYZE_PRINTF1 ("Generating virtual stop bit\n");
got_light = TRUE; // this is a lie, but helps (generates stop bit)
}
else if (irmp_pulse_time >= FAN_1_PULSE_LEN_MIN && irmp_pause_time >= FAN_1_PAUSE_LEN_MIN)
{
ANALYZE_PRINTF1 ("Generating virtual stop bit\n");
got_light = TRUE; // this is a lie, but helps (generates stop bit)
}
}
else
#endif
#if IRMP_SUPPORT_SERIAL == 1
// NETBOX generates no stop bit, here is the timeout condition:
if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) && irmp_param.protocol == IRMP_NETBOX_PROTOCOL &&
irmp_pause_time >= NETBOX_PULSE_LEN * (NETBOX_COMPLETE_DATA_LEN - irmp_bit))
{
got_light = TRUE; // this is a lie, but helps (generates stop bit)
}
else
#endif
#if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1
if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && !irmp_param.stop_bit)
{
if (irmp_pause_time > IR60_TIMEOUT_LEN && (irmp_bit == 5 || irmp_bit == 6))
{
ANALYZE_PRINTF1 ("Switching to IR60 protocol\n");
got_light = TRUE; // this is a lie, but generates a stop bit ;-)
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_IR60_PROTOCOL; // change protocol
irmp_param.complete_len = IR60_COMPLETE_DATA_LEN; // correct complete len
irmp_param.address_offset = IR60_ADDRESS_OFFSET;
irmp_param.address_end = IR60_ADDRESS_OFFSET + IR60_ADDRESS_LEN;
irmp_param.command_offset = IR60_COMMAND_OFFSET;
irmp_param.command_end = IR60_COMMAND_OFFSET + IR60_COMMAND_LEN;
irmp_tmp_command <<= 1;
irmp_tmp_command |= first_bit;
}
else if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2)
{ // special manchester decoder
irmp_param.complete_len = GRUNDIG_COMPLETE_DATA_LEN; // correct complete len
got_light = TRUE; // this is a lie, but generates a stop bit ;-)
irmp_param.stop_bit = TRUE; // set flag
}
else if (irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN)
{
ANALYZE_PRINTF2 ("Switching to NOKIA protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.protocol = IRMP_NOKIA_PROTOCOL; // change protocol
irmp_param.address_offset = NOKIA_ADDRESS_OFFSET;
irmp_param.address_end = NOKIA_ADDRESS_OFFSET + NOKIA_ADDRESS_LEN;
irmp_param.command_offset = NOKIA_COMMAND_OFFSET;
irmp_param.command_end = NOKIA_COMMAND_OFFSET + NOKIA_COMMAND_LEN;
if (irmp_tmp_command & 0x300)
{
irmp_tmp_address = (irmp_tmp_command >> 8);
irmp_tmp_command &= 0xFF;
}
}
}
else
#endif
#if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RUWIDO_PROTOCOL && !irmp_param.stop_bit)
{
if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= RUWIDO_COMPLETE_DATA_LEN - 2)
{ // special manchester decoder
irmp_param.complete_len = RUWIDO_COMPLETE_DATA_LEN; // correct complete len
got_light = TRUE; // this is a lie, but generates a stop bit ;-)
irmp_param.stop_bit = TRUE; // set flag
}
else if (irmp_bit >= RUWIDO_COMPLETE_DATA_LEN)
{
ANALYZE_PRINTF1 ("Switching to SIEMENS protocol\n");
irmp_param.protocol = IRMP_SIEMENS_PROTOCOL; // change protocol
irmp_param.address_offset = SIEMENS_ADDRESS_OFFSET;
irmp_param.address_end = SIEMENS_ADDRESS_OFFSET + SIEMENS_ADDRESS_LEN;
irmp_param.command_offset = SIEMENS_COMMAND_OFFSET;
irmp_param.command_end = SIEMENS_COMMAND_OFFSET + SIEMENS_COMMAND_LEN;
// 76543210
// RUWIDO: AAAAAAAAACCCCCCCp
// SIEMENS: AAAAAAAAAAACCCCCCCCCCp
irmp_tmp_address <<= 2;
irmp_tmp_address |= (irmp_tmp_command >> 6);
irmp_tmp_command &= 0x003F;
irmp_tmp_command |= last_value;
}
}
else
#endif
#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
if (irmp_param.protocol == IRMP_ROOMBA_PROTOCOL && // Roomba has no stop bit
irmp_bit >= ROOMBA_COMPLETE_DATA_LEN - 1) // it's the last data bit...
{ // break and close this frame
if (irmp_pulse_time >= ROOMBA_1_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_1_PULSE_LEN_MAX)
{
irmp_pause_time = ROOMBA_1_PAUSE_LEN_EXACT;
}
else if (irmp_pulse_time >= ROOMBA_0_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_0_PULSE_LEN_MAX)
{
irmp_pause_time = ROOMBA_0_PAUSE_LEN;
}
got_light = TRUE; // this is a lie, but helps (generates stop bit)
}
else
#endif
#if IRMP_SUPPORT_MANCHESTER == 1
if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) &&
(irmp_param.protocol != IRMP_RC6_PROTOCOL || irmp_param.complete_len != RC6_COMPLETE_DATA_LEN_LONG) && // not RC6A
irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= irmp_param.complete_len - 2 && !irmp_param.stop_bit)
{ // special manchester decoder
got_light = TRUE; // this is a lie, but generates a stop bit ;-)
irmp_param.stop_bit = TRUE; // set flag
}
else if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) &&
irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG && // RC6A
irmp_pause_time >= 2 * irmp_param.pause_1_len_max) // this pause indicates the end
{ // special manchester decoder
got_light = TRUE; // this is a lie, but generates a stop bit ;-)
irmp_param.stop_bit = TRUE; // set flag
irmp_param.complete_len = irmp_bit + 1; // at least 1 more bit will be added at last position
}
else
#endif // IRMP_SUPPORT_MANCHESTER == 1
if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout?
{ // yes...
if (irmp_bit == irmp_param.complete_len - 1 && irmp_param.stop_bit == 0)
{
irmp_bit++;
}
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
else if ((irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL) && irmp_bit == 0)
{ // it was a non-standard repetition frame
ANALYZE_PRINTF1 ("Detected non-standard repetition frame, switching to NEC repetition\n");
if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX)
{
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
irmp_tmp_address = last_irmp_address; // address is last address
irmp_tmp_command = last_irmp_command; // command is last command
irmp_flags |= IRMP_FLAG_REPETITION;
key_repetition_len = 0;
}
else
{
ANALYZE_PRINTF3 ("ignoring NEC repetition frame: timeout occured, key_repetition_len = %u > %u\n",
(unsigned int) key_repetition_len, (unsigned int) NEC_FRAME_REPEAT_PAUSE_LEN_MAX);
irmp_ir_detected = FALSE;
}
}
#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit
{
ANALYZE_PRINTF2 ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
irmp_tmp_command = (irmp_tmp_address >> 4); // set command: upper 12 bits are command bits
irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits
irmp_start_bit_detected = 1; // tricky: don't wait for another start bit...
}
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 28 || irmp_bit == 29)) // it was a LGAIR stop bit
{
ANALYZE_PRINTF2 ("Switching to LGAIR protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
irmp_tmp_command = irmp_lgair_command; // set command: upper 8 bits are command bits
irmp_tmp_address = irmp_lgair_address; // lower 4 bits are address bits
irmp_start_bit_detected = 1; // tricky: don't wait for another start bit...
}
#endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 32) // it was a NEC stop bit
{
ANALYZE_PRINTF1 ("Switching to NEC protocol\n");
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
// 0123456789ABC0123456789ABC0123456701234567
// NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc
// NEC: AAAAAAAAaaaaaaaaCCCCCCCCcccccccc
irmp_tmp_address |= (irmp_tmp_address2 & 0x0007) << 13; // fm 2012-02-13: 12 -> 13
irmp_tmp_command = (irmp_tmp_address2 >> 3) | (irmp_tmp_command << 10);
}
#endif // IRMP_SUPPORT_NEC_PROTOCOL == 1
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 28) // it was a NEC stop bit
{
ANALYZE_PRINTF1 ("Switching to LGAIR protocol\n");
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
irmp_tmp_address = irmp_lgair_address;
irmp_tmp_command = irmp_lgair_command;
}
#endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit
{
ANALYZE_PRINTF2 ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.stop_bit = TRUE; // set flag
irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length: 16 or 17
// 0123456789ABC0123456789ABC0123456701234567
// NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc
// JVC: AAAACCCCCCCCCCCC
irmp_tmp_command = (irmp_tmp_address >> 4) | (irmp_tmp_address2 << 9); // set command: upper 12 bits are command bits
irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits
}
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit == 32) // it was a SAMSUNG32 stop bit
{
ANALYZE_PRINTF1 ("Switching to SAMSUNG32 protocol\n");
irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL;
irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET;
irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN;
irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN;
}
#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL && (irmp_bit == 12 || irmp_bit == 24)) // it was a RCMM stop bit
{
if (irmp_bit == 12)
{
irmp_tmp_command = (irmp_tmp_address & 0xFF); // set command: lower 8 bits are command bits
irmp_tmp_address >>= 8; // upper 4 bits are address bits
ANALYZE_PRINTF2 ("Switching to RCMM12 protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.protocol = IRMP_RCMM12_PROTOCOL; // switch protocol
}
else // if ((irmp_bit == 24)
{
ANALYZE_PRINTF2 ("Switching to RCMM24 protocol, irmp_bit = %d\n", irmp_bit);
irmp_param.protocol = IRMP_RCMM24_PROTOCOL; // switch protocol
}
irmp_param.stop_bit = TRUE; // set flag
irmp_param.complete_len = irmp_bit; // patch length
}
#endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1
#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1
else if (irmp_param.protocol == IRMP_MATSUSHITA_PROTOCOL && irmp_bit == 22) // it was a TECHNICS stop bit
{
ANALYZE_PRINTF2 ("Switching to TECHNICS protocol, irmp_bit = %d\n", irmp_bit);
// Situation:
// The first 12 bits have been stored in irmp_tmp_command (LSB first)
// The following 10 bits have been stored in irmp_tmp_address (LSB first)
// The code of TECHNICS is:
// cccccccccccCCCCCCCCCCC (11 times c and 11 times C)
// ccccccccccccaaaaaaaaaa
// where C is inverted value of c
irmp_tmp_address <<= 1;
if (irmp_tmp_command & (1<<11))
{
irmp_tmp_address |= 1;
irmp_tmp_command &= ~(1<<11);
}
if (irmp_tmp_command == ((~irmp_tmp_address) & 0x07FF))
{
irmp_tmp_address = 0;
irmp_param.protocol = IRMP_TECHNICS_PROTOCOL; // switch protocol
irmp_param.complete_len = irmp_bit; // patch length
}
else
{
ANALYZE_PRINTF1 ("error 8: TECHNICS frame error\n");
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // wait for another start bit...
irmp_pulse_time = 0;
irmp_pause_time = 0;
}
}
#endif // IRMP_SUPPORT_TECHNICS_PROTOCOL == 1
else
{
ANALYZE_PRINTF3 ("error 2: pause %d after data bit %d too long\n", irmp_pause_time, irmp_bit);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // wait for another start bit...
irmp_pulse_time = 0;
irmp_pause_time = 0;
}
}
}
else
{ // got light now!
got_light = TRUE;
}
if (got_light)
{
ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time);
#if IRMP_SUPPORT_MANCHESTER == 1
if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) // Manchester
{
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
if (irmp_param.complete_len == irmp_bit && irmp_param.protocol == IRMP_MERLIN_PROTOCOL)
{
if (last_value == 0)
{
if (irmp_pulse_time >= 2 * irmp_param.pulse_1_len_min && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max &&
last_pause >= irmp_param.pause_1_len_min && last_pause <= irmp_param.pulse_1_len_max)
{
irmp_param.complete_len += 2;
irmp_store_bit(0);
irmp_store_bit(1);
ANALYZE_PUTCHAR ('0');
ANALYZE_PUTCHAR ('1');
ANALYZE_NEWLINE ();
}
}
else
{
if (last_pause >= 2 * irmp_param.pause_1_len_min && last_pause <= 2 * irmp_param.pulse_1_len_max)
{
if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max)
{
irmp_param.complete_len++;
irmp_store_bit(0);
ANALYZE_PUTCHAR ('0');
ANALYZE_NEWLINE ();
}
else if (irmp_pulse_time >= 2 * irmp_param.pulse_1_len_min && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max)
{
irmp_param.complete_len += 2;
irmp_store_bit(0);
irmp_store_bit(1);
ANALYZE_PUTCHAR ('0');
ANALYZE_PUTCHAR ('1');
ANALYZE_NEWLINE ();
}
}
}
}
else
#endif
#if 1
if (irmp_pulse_time > irmp_param.pulse_1_len_max /* && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max */)
#else // better, but some IR-RCs use asymmetric timings :-/
if (irmp_pulse_time > irmp_param.pulse_1_len_max && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max &&
irmp_pause_time <= 2 * irmp_param.pause_1_len_max)
#endif
{
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == irmp_bit + 1) // RC6A
{
irmp_param.complete_len++; // this is the last position and 2 bits (instead of only 1) will be added
}
if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit
{
ANALYZE_PUTCHAR ('T');
if (irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode 6A
{
irmp_store_bit (1);
last_value = 1;
}
else // RC6 mode 0
{
irmp_store_bit (0);
last_value = 0;
}
ANALYZE_NEWLINE ();
}
else
#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1
{
ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1');
irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1 );
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit
{
ANALYZE_PUTCHAR ('T');
irmp_store_bit (1);
if (irmp_pause_time > 2 * irmp_param.pause_1_len_max)
{
last_value = 0;
}
else
{
last_value = 1;
}
ANALYZE_NEWLINE ();
}
else
#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1
{
ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0');
irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0 );
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
if (! irmp_param2.protocol)
#endif
{
ANALYZE_NEWLINE ();
}
last_value = (irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0;
}
}
}
else if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max
/* && irmp_pause_time <= 2 * irmp_param.pause_1_len_max */)
{
uint_fast8_t manchester_value;
if (last_pause > irmp_param.pause_1_len_max && last_pause <= 2 * irmp_param.pause_1_len_max)
{
manchester_value = last_value ? 0 : 1;
last_value = manchester_value;
}
else
{
manchester_value = last_value;
}
ANALYZE_PUTCHAR (manchester_value + '0');
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)
if (! irmp_param2.protocol)
#endif
{
ANALYZE_NEWLINE ();
}
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 1 && manchester_value == 1) // RC6 mode != 0 ???
{
ANALYZE_PRINTF1 ("Switching to RC6A protocol\n");
irmp_param.complete_len = RC6_COMPLETE_DATA_LEN_LONG;
irmp_param.address_offset = 5;
irmp_param.address_end = irmp_param.address_offset + 15;
irmp_param.command_offset = irmp_param.address_end + 1; // skip 1 system bit, changes like a toggle bit
irmp_param.command_end = irmp_param.command_offset + 16 - 1;
irmp_tmp_address = 0;
}
#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1
irmp_store_bit (manchester_value);
}
else
{
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1
if (irmp_param2.protocol == IRMP_FDC_PROTOCOL &&
irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX &&
((irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) ||
(irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX)))
{
ANALYZE_PUTCHAR ('?');
irmp_param.protocol = 0; // switch to FDC, see below
}
else
#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1
if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL &&
irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX &&
((irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) ||
(irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX)))
{
ANALYZE_PUTCHAR ('?');
irmp_param.protocol = 0; // switch to RCCAR, see below
}
else
#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1
{
ANALYZE_PUTCHAR ('?');
ANALYZE_NEWLINE ();
ANALYZE_PRINTF4 ("error 3 manchester: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1
if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX)
{
if (irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 (" 1 (FDC)\n");
irmp_store_bit2 (1);
}
else if (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 (" 0 (FDC)\n");
irmp_store_bit2 (0);
}
if (! irmp_param.protocol)
{
ANALYZE_PRINTF1 ("Switching to FDC protocol\n");
memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER));
irmp_param2.protocol = 0;
irmp_tmp_address = irmp_tmp_address2;
irmp_tmp_command = irmp_tmp_command2;
}
}
#endif // IRMP_SUPPORT_FDC_PROTOCOL == 1
#if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1
if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX)
{
if (irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 (" 1 (RCCAR)\n");
irmp_store_bit2 (1);
}
else if (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 (" 0 (RCCAR)\n");
irmp_store_bit2 (0);
}
if (! irmp_param.protocol)
{
ANALYZE_PRINTF1 ("Switching to RCCAR protocol\n");
memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER));
irmp_param2.protocol = 0;
irmp_tmp_address = irmp_tmp_address2;
irmp_tmp_command = irmp_tmp_command2;
}
}
#endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1
last_pause = irmp_pause_time;
wait_for_space = 0;
}
else
#endif // IRMP_SUPPORT_MANCHESTER == 1
#if IRMP_SUPPORT_SERIAL == 1
if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL)
{
while (irmp_bit < irmp_param.complete_len && irmp_pulse_time > irmp_param.pulse_1_len_max)
{
ANALYZE_PUTCHAR ('1');
irmp_store_bit (1);
if (irmp_pulse_time >= irmp_param.pulse_1_len_min)
{
irmp_pulse_time -= irmp_param.pulse_1_len_min;
}
else
{
irmp_pulse_time = 0;
}
}
while (irmp_bit < irmp_param.complete_len && irmp_pause_time > irmp_param.pause_1_len_max)
{
ANALYZE_PUTCHAR ('0');
irmp_store_bit (0);
if (irmp_pause_time >= irmp_param.pause_1_len_min)
{
irmp_pause_time -= irmp_param.pause_1_len_min;
}
else
{
irmp_pause_time = 0;
}
}
ANALYZE_NEWLINE ();
wait_for_space = 0;
}
else
#endif // IRMP_SUPPORT_SERIAL == 1
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit == 16) // Samsung: 16th bit
{
if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX &&
irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("SYNC\n");
wait_for_space = 0;
irmp_bit++;
}
else if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX)
{
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
ANALYZE_PRINTF1 ("Switching to SAMSUNG48 protocol ");
irmp_param.protocol = IRMP_SAMSUNG48_PROTOCOL;
irmp_param.command_offset = SAMSUNG48_COMMAND_OFFSET;
irmp_param.command_end = SAMSUNG48_COMMAND_OFFSET + SAMSUNG48_COMMAND_LEN;
irmp_param.complete_len = SAMSUNG48_COMPLETE_DATA_LEN;
#else
ANALYZE_PRINTF1 ("Switching to SAMSUNG32 protocol ");
irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL;
irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET;
irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN;
irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN;
#endif
if (irmp_pause_time >= SAMSUNG_1_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_1_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('1');
ANALYZE_NEWLINE ();
irmp_store_bit (1);
wait_for_space = 0;
}
else
{
ANALYZE_PUTCHAR ('0');
ANALYZE_NEWLINE ();
irmp_store_bit (0);
wait_for_space = 0;
}
}
else
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3 Samsung: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
else
#endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL
#if IRMP_SUPPORT_NEC16_PROTOCOL
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC42_PROTOCOL &&
#else // IRMP_SUPPORT_NEC_PROTOCOL instead
if (irmp_param.protocol == IRMP_NEC_PROTOCOL &&
#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1
irmp_bit == 8 && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("Switching to NEC16 protocol\n");
irmp_param.protocol = IRMP_NEC16_PROTOCOL;
irmp_param.address_offset = NEC16_ADDRESS_OFFSET;
irmp_param.address_end = NEC16_ADDRESS_OFFSET + NEC16_ADDRESS_LEN;
irmp_param.command_offset = NEC16_COMMAND_OFFSET;
irmp_param.command_end = NEC16_COMMAND_OFFSET + NEC16_COMMAND_LEN;
irmp_param.complete_len = NEC16_COMPLETE_DATA_LEN;
wait_for_space = 0;
}
else
#endif // IRMP_SUPPORT_NEC16_PROTOCOL
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL)
{
if (irmp_pulse_time >= BANG_OLUFSEN_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_PULSE_LEN_MAX)
{
if (irmp_bit == 1) // Bang & Olufsen: 3rd bit
{
if (irmp_pause_time >= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("3rd start bit\n");
wait_for_space = 0;
irmp_bit++;
}
else
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3a B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
else if (irmp_bit == 19) // Bang & Olufsen: trailer bit
{
if (irmp_pause_time >= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF1 ("trailer bit\n");
wait_for_space = 0;
irmp_bit++;
}
else
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3b B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
else
{
if (irmp_pause_time >= BANG_OLUFSEN_1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_1_PAUSE_LEN_MAX)
{ // pulse & pause timings correct for "1"?
ANALYZE_PUTCHAR ('1');
ANALYZE_NEWLINE ();
irmp_store_bit (1);
last_value = 1;
wait_for_space = 0;
}
else if (irmp_pause_time >= BANG_OLUFSEN_0_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_0_PAUSE_LEN_MAX)
{ // pulse & pause timings correct for "0"?
ANALYZE_PUTCHAR ('0');
ANALYZE_NEWLINE ();
irmp_store_bit (0);
last_value = 0;
wait_for_space = 0;
}
else if (irmp_pause_time >= BANG_OLUFSEN_R_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_R_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR (last_value + '0');
ANALYZE_NEWLINE ();
irmp_store_bit (last_value);
wait_for_space = 0;
}
else
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3c B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
}
else
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3d B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
}
else
#endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL)
{
if (irmp_pause_time >= RCMM32_BIT_00_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_00_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('0');
ANALYZE_PUTCHAR ('0');
irmp_store_bit (0);
irmp_store_bit (0);
}
else if (irmp_pause_time >= RCMM32_BIT_01_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_01_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('0');
ANALYZE_PUTCHAR ('1');
irmp_store_bit (0);
irmp_store_bit (1);
}
else if (irmp_pause_time >= RCMM32_BIT_10_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_10_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('1');
ANALYZE_PUTCHAR ('0');
irmp_store_bit (1);
irmp_store_bit (0);
}
else if (irmp_pause_time >= RCMM32_BIT_11_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_11_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('1');
ANALYZE_PUTCHAR ('1');
irmp_store_bit (1);
irmp_store_bit (1);
}
ANALYZE_PRINTF1 ("\n");
wait_for_space = 0;
}
else
#endif
if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max &&
irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max)
{ // pulse & pause timings correct for "1"?
ANALYZE_PUTCHAR ('1');
ANALYZE_NEWLINE ();
irmp_store_bit (1);
wait_for_space = 0;
}
else if (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max &&
irmp_pause_time >= irmp_param.pause_0_len_min && irmp_pause_time <= irmp_param.pause_0_len_max)
{ // pulse & pause timings correct for "0"?
ANALYZE_PUTCHAR ('0');
ANALYZE_NEWLINE ();
irmp_store_bit (0);
wait_for_space = 0;
}
else
#if IRMP_SUPPORT_KATHREIN_PROTOCOL
if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL &&
irmp_pulse_time >= KATHREIN_1_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_1_PULSE_LEN_MAX &&
(((irmp_bit == 8 || irmp_bit == 6) &&
irmp_pause_time >= KATHREIN_SYNC_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_SYNC_BIT_PAUSE_LEN_MAX) ||
(irmp_bit == 12 &&
irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX)))
{
if (irmp_bit == 8)
{
irmp_bit++;
ANALYZE_PUTCHAR ('S');
ANALYZE_NEWLINE ();
irmp_tmp_command <<= 1;
}
else
{
ANALYZE_PUTCHAR ('S');
ANALYZE_NEWLINE ();
irmp_store_bit (1);
}
wait_for_space = 0;
}
else
#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC42_PROTOCOL &&
#else // IRMP_SUPPORT_NEC_PROTOCOL instead
if (irmp_param.protocol == IRMP_NEC_PROTOCOL &&
#endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1
(
(irmp_pulse_time >= MELINERA_0_PULSE_LEN_MIN && irmp_pulse_time <= MELINERA_0_PULSE_LEN_MAX &&
irmp_pause_time >= MELINERA_0_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_0_PAUSE_LEN_MAX) ||
(irmp_pulse_time >= MELINERA_1_PULSE_LEN_MIN && irmp_pulse_time <= MELINERA_1_PULSE_LEN_MAX &&
irmp_pause_time >= MELINERA_1_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_1_PAUSE_LEN_MAX)
))
{
ANALYZE_PRINTF1 ("Switching to MELINERA protocol ");
irmp_param.protocol = IRMP_MELINERA_PROTOCOL;
irmp_param.pulse_0_len_min = MELINERA_0_PULSE_LEN_MIN;
irmp_param.pulse_0_len_max = MELINERA_0_PULSE_LEN_MAX;
irmp_param.pause_0_len_min = MELINERA_0_PAUSE_LEN_MIN;
irmp_param.pulse_0_len_max = MELINERA_0_PAUSE_LEN_MAX;
irmp_param.pulse_1_len_min = MELINERA_1_PULSE_LEN_MIN;
irmp_param.pulse_1_len_max = MELINERA_1_PULSE_LEN_MAX;
irmp_param.pause_1_len_min = MELINERA_1_PAUSE_LEN_MIN;
irmp_param.pulse_1_len_max = MELINERA_1_PAUSE_LEN_MAX;
irmp_param.address_offset = MELINERA_ADDRESS_OFFSET;
irmp_param.address_end = MELINERA_ADDRESS_OFFSET + MELINERA_ADDRESS_LEN;
irmp_param.command_offset = MELINERA_COMMAND_OFFSET;
irmp_param.command_end = MELINERA_COMMAND_OFFSET + MELINERA_COMMAND_LEN;
irmp_param.complete_len = MELINERA_COMPLETE_DATA_LEN;
if (irmp_pause_time >= MELINERA_0_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_0_PAUSE_LEN_MAX)
{
ANALYZE_PUTCHAR ('0');
irmp_store_bit (0);
}
else
{
ANALYZE_PUTCHAR ('1');
irmp_store_bit (1);
}
ANALYZE_NEWLINE ();
wait_for_space = 0;
}
else
#endif // IRMP_SUPPORT_MELINERA_PROTOCOL
{ // timing incorrect!
ANALYZE_PRINTF4 ("error 3: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time);
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
irmp_start_bit_detected = 0; // reset flags and wait for next start bit
irmp_pause_time = 0;
}
irmp_pulse_time = 1; // set counter to 1, not 0
}
}
else
{ // counting the pulse length ...
if (! irmp_input) // still light?
{ // yes...
irmp_pulse_time++; // increment counter
}
else
{ // now it's dark!
wait_for_space = 1; // let's count the time (see above)
irmp_pause_time = 1; // set pause counter to 1, not 0
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RCII_PROTOCOL && waiting_for_2nd_pulse)
{
// fm: output is "1000 466" or "1533 466"
// printf ("fm: %d %d\n", irmp_pulse_time * 1000000 / F_INTERRUPTS, RCII_BIT_LEN * 1000000 / F_INTERRUPTS);
irmp_pulse_time -= RCII_BIT_LEN;
last_value = 0;
ANALYZE_PRINTF2 ("RCII: got 2nd pulse, irmp_pulse_time = %d\n", irmp_pulse_time);
waiting_for_2nd_pulse = 0;
}
#endif
}
}
if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0) // enough bits received?
{
if (last_irmp_command == irmp_tmp_command && key_repetition_len < AUTO_FRAME_REPETITION_LEN)
{
repetition_frame_number++;
}
else
{
repetition_frame_number = 0;
}
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
// if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame
if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2))
{
ANALYZE_PRINTF4 ("code skipped: SIRCS auto repetition frame #%d, counter = %u, auto repetition len = %u\n",
repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
// if ORTEK protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame
if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL && repetition_frame_number == 1)
{
ANALYZE_PRINTF4 ("code skipped: ORTEK auto repetition frame #%d, counter = %d, auto repetition len = %d\n",
repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
#if 0 && IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame
// if KASEIKYO protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame
if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL && repetition_frame_number == 1)
{
ANALYZE_PRINTF4 ("code skipped: KASEIKYO auto repetition frame #%d, counter = %d, auto repetition len = %d\n",
repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
#if 0 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame
// if SAMSUNG32 or SAMSUNG48 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame
if ((irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL || irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL) && (repetition_frame_number & 0x01))
{
ANALYZE_PRINTF4 ("code skipped: SAMSUNG32/SAMSUNG48 auto repetition frame #%d, counter = %d, auto repetition len = %d\n",
repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1
// if NUBERT protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame
if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01))
{
ANALYZE_PRINTF4 ("code skipped: NUBERT auto repetition frame #%d, counter = %u, auto repetition len = %u\n",
repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
// if SPEAKER protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame
if (irmp_param.protocol == IRMP_SPEAKER_PROTOCOL && (repetition_frame_number & 0x01))
{
ANALYZE_PRINTF4 ("code skipped: SPEAKER auto repetition frame #%d, counter = %u, auto repetition len = %u\n",
repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN);
key_repetition_len = 0;
}
else
#endif
{
ANALYZE_PRINTF3 ("%8.3fms code detected, length = %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit);
irmp_ir_detected = TRUE;
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && irmp_tmp_command == 0x0000)
{
if (irmp_tmp_command == 0x0000) // KATHREIN sends key release with command = 0x0000, ignore it
{
ANALYZE_PRINTF1 ("got KATHREIN release command, ignore it\n");
irmp_ir_detected = FALSE;
}
}
else
#endif // IRMP_SUPPORT_KATHREIN_PROTOCOL
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
if (irmp_param.protocol == IRMP_DENON_PROTOCOL)
{ // check for repetition frame
if ((~irmp_tmp_command & 0x3FF) == last_irmp_denon_command) // command bits must be inverted
{
irmp_tmp_command = last_irmp_denon_command; // use command received before!
last_irmp_denon_command = 0;
irmp_protocol = irmp_param.protocol; // store protocol
irmp_address = irmp_tmp_address; // store address
irmp_command = irmp_tmp_command; // store command
}
else
{
if ((irmp_tmp_command & 0x01) == 0x00)
{
ANALYZE_PRINTF2 ("%8.3fms info Denon: waiting for inverted command repetition\n", (double) (time_counter * 1000) / F_INTERRUPTS);
last_irmp_denon_command = irmp_tmp_command;
denon_repetition_len = 0;
irmp_ir_detected = FALSE;
}
else
{
ANALYZE_PRINTF2 ("%8.3fms warning Denon: got unexpected inverted command, ignoring it\n", (double) (time_counter * 1000) / F_INTERRUPTS);
last_irmp_denon_command = 0;
irmp_ir_detected = FALSE;
}
}
}
else
#endif // IRMP_SUPPORT_DENON_PROTOCOL
#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1
if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff)
{ // Grundig start frame?
ANALYZE_PRINTF1 ("Detected GRUNDIG start frame, ignoring it\n");
irmp_ir_detected = FALSE;
}
else
#endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL
#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NOKIA_PROTOCOL && irmp_tmp_address == 0x00ff && irmp_tmp_command == 0x00fe)
{ // Nokia start frame?
ANALYZE_PRINTF1 ("Detected NOKIA start frame, ignoring it\n");
irmp_ir_detected = FALSE;
}
else
#endif // IRMP_SUPPORT_NOKIA_PROTOCOL
{
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0) // repetition frame
{
if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX)
{
ANALYZE_PRINTF2 ("Detected NEC repetition frame, key_repetition_len = %u\n", (unsigned int) key_repetition_len);
ANALYZE_ONLY_NORMAL_PRINTF1("REPETETION FRAME ");
irmp_tmp_address = last_irmp_address; // address is last address
irmp_tmp_command = last_irmp_command; // command is last command
irmp_flags |= IRMP_FLAG_REPETITION;
key_repetition_len = 0;
}
else
{
ANALYZE_PRINTF3 ("Detected NEC repetition frame, ignoring it: timeout occured, key_repetition_len = %u > %u\n",
(unsigned int) key_repetition_len, (unsigned int) NEC_FRAME_REPEAT_PAUSE_LEN_MAX);
irmp_ir_detected = FALSE;
}
}
#endif // IRMP_SUPPORT_NEC_PROTOCOL
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL)
{
uint_fast8_t xor_value;
xor_value = (xor_check[0] & 0x0F) ^ ((xor_check[0] & 0xF0) >> 4) ^ (xor_check[1] & 0x0F) ^ ((xor_check[1] & 0xF0) >> 4);
if (xor_value != (xor_check[2] & 0x0F))
{
ANALYZE_PRINTF3 ("error 4: wrong XOR check for customer id: 0x%1x 0x%1x\n", xor_value, xor_check[2] & 0x0F);
irmp_ir_detected = FALSE;
}
xor_value = xor_check[2] ^ xor_check[3] ^ xor_check[4];
if (xor_value != xor_check[5])
{
ANALYZE_PRINTF3 ("error 5: wrong XOR check for data bits: 0x%02x 0x%02x\n", xor_value, xor_check[5]);
irmp_ir_detected = FALSE;
}
irmp_flags |= genre2; // write the genre2 bits into MSB of the flag byte
}
#endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL)
{
if (parity == PARITY_CHECK_FAILED)
{
ANALYZE_PRINTF1 ("error 6: parity check failed\n");
irmp_ir_detected = FALSE;
}
if ((irmp_tmp_address & 0x03) == 0x02)
{
ANALYZE_PRINTF1 ("code skipped: ORTEK end of transmission frame (key release)\n");
irmp_ir_detected = FALSE;
}
irmp_tmp_address >>= 2;
}
#endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL)
{
check = irmp_tmp_command >> 8; // inverted upper byte == lower byte?
check = ~ check;
if (check == (irmp_tmp_command & 0xFF)) { //ok:
irmp_tmp_command &= 0xFF;
}
else mitsu_parity = PARITY_CHECK_FAILED;
if (mitsu_parity == PARITY_CHECK_FAILED)
{
ANALYZE_PRINTF1 ("error 7: parity check failed\n");
irmp_ir_detected = FALSE;
}
}
#endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode = 6?
{
irmp_protocol = IRMP_RC6A_PROTOCOL;
}
else if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_20) // RC6 mode = 6?
{
irmp_protocol = IRMP_RC6A20_PROTOCOL;
}
else if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_28) // RC6 mode = 6?
{
irmp_protocol = IRMP_RC6A28_PROTOCOL;
}
else
#endif // IRMP_SUPPORT_RC6_PROTOCOL == 1
{
irmp_protocol = irmp_param.protocol;
}
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
if (irmp_param.protocol == IRMP_FDC_PROTOCOL)
{
if (irmp_tmp_command & 0x000F) // released key?
{
irmp_tmp_command = (irmp_tmp_command >> 4) | 0x80; // yes, set bit 7
}
else
{
irmp_tmp_command >>= 4; // no, it's a pressed key
}
irmp_tmp_command |= (irmp_tmp_address << 2) & 0x0F00; // 000000CCCCAAAAAA -> 0000CCCC00000000
irmp_tmp_address &= 0x003F;
}
#endif
irmp_address = irmp_tmp_address; // store address
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
if (irmp_param.protocol == IRMP_NEC_PROTOCOL)
{
last_irmp_address = irmp_tmp_address; // store as last address, too
}
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
if (irmp_param.protocol == IRMP_RC5_PROTOCOL)
{
irmp_tmp_command |= rc5_cmd_bit6; // store bit 6
}
#endif
#if IRMP_SUPPORT_S100_PROTOCOL == 1
if (irmp_param.protocol == IRMP_S100_PROTOCOL)
{
irmp_tmp_command |= rc5_cmd_bit6; // store bit 6
}
#endif
irmp_command = irmp_tmp_command; // store command
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
irmp_id = irmp_tmp_id;
#endif
}
}
if (irmp_ir_detected)
{
if (last_irmp_command == irmp_tmp_command &&
last_irmp_address == irmp_tmp_address &&
#if IRMP_AUTODETECT_REPEATRATE
irmp_protocol == previous_irmp_protocol)
{
same_key = 1;
}
pass_on_delta_detection = delta_detection;
delta_detection = 0;
#else
key_repetition_len < IRMP_KEY_REPETITION_LEN) // time after data frame, not total since start
{
irmp_flags |= IRMP_FLAG_REPETITION;
}
#endif
last_irmp_address = irmp_tmp_address; // store as last address, too
last_irmp_command = irmp_tmp_command; // store as last command, too
#if IRMP_ENABLE_RELEASE_DETECTION == 1
key_released = FALSE;
#endif
key_repetition_len = 0;
}
else
{
ANALYZE_ONLY_NORMAL_PUTCHAR ('\n');
}
irmp_start_bit_detected = 0; // and wait for next start bit
irmp_tmp_command = 0;
irmp_pulse_time = 0;
irmp_pause_time = 0;
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
if (irmp_protocol == IRMP_JVC_PROTOCOL) // the stop bit of JVC frame is also start bit of next frame
{ // set pulse time here!
irmp_pulse_time = ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME));
}
#endif // IRMP_SUPPORT_JVC_PROTOCOL == 1
}
}
}
#if defined(STELLARIS_ARM_CORTEX_M4)
// Clear the timer interrupt
TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
#endif
#if (defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_)) && IRMP_USE_EVENT == 1
if (IRMP_EVENT_THREAD_PTR != nullptr && irmp_ir_detected)
chEvtSignalI(IRMP_EVENT_THREAD_PTR,IRMP_EVENT_BIT);
#endif
#if IRMP_USE_COMPLETE_CALLBACK == 1
if (irmp_complete_callback_function != nullptr && irmp_ir_detected) {
irmp_complete_callback_function();
}
#endif
#if IRMP_USE_IDLE_CALL == 1
// check if there is no ongoing transmission or repetition
if (!irmp_start_bit_detected && !irmp_pulse_time
&& key_repetition_len > IRMP_KEY_REPETITION_LEN)
{
// no ongoing transmission
// enough time passed since last decoded signal that a repetition won't affect our output
irmp_idle();
}
#endif // IRMP_USE_IDLE_CALL
return (irmp_ir_detected);
}
#if defined(ANALYZE)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* main functions - for Unix/Linux + Windows only!
*
* AVR: see main.c!
*
* Compile it under linux with:
* cc irmp.c -o irmp
*
* usage: ./irmp [-v|-s|-a|-l] < file
*
* options:
* -v verbose
* -s silent
* -a analyze
* -l list pulse/pauses
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
void
print_spectrum (const char *text, int *buf, int is_pulse)
{
int i;
int j;
int min;
int max;
int max_value = 0;
int value;
int sum = 0;
int counter = 0;
double average = 0;
double tolerance;
puts ("-----------------------------------------------------------------------------");
printf ("%s:\n", text);
for (i = 0; i < 256; i++)
{
if (buf[i] > max_value)
{
max_value = buf[i];
}
}
for (i = 1; i < 200; i++)
{
if (buf[i] > 0)
{
printf ("%3d ", i);
value = (buf[i] * 60) / max_value;
for (j = 0; j < value; j++)
{
putchar ('o');
}
printf (" %d\n", buf[i]);
sum += i * buf[i];
counter += buf[i];
}
else
{
max = i - 1;
if (counter > 0)
{
average = (float) sum / (float) counter;
if (is_pulse)
{
printf ("pulse ");
}
else
{
printf ("pause ");
}
printf ("avg: %4.1f=%6.1f us, ", average, (1000000. * average) / (float) F_INTERRUPTS);
printf ("min: %2d=%6.1f us, ", min, (1000000. * min) / (float) F_INTERRUPTS);
printf ("max: %2d=%6.1f us, ", max, (1000000. * max) / (float) F_INTERRUPTS);
tolerance = (max - average);
if (average - min > tolerance)
{
tolerance = average - min;
}
tolerance = tolerance * 100 / average;
printf ("tol: %4.1f%%\n", tolerance);
}
counter = 0;
sum = 0;
min = i + 1;
}
}
}
#define STATE_LEFT_SHIFT 0x01
#define STATE_RIGHT_SHIFT 0x02
#define STATE_LEFT_CTRL 0x04
#define STATE_LEFT_ALT 0x08
#define STATE_RIGHT_ALT 0x10
#define KEY_ESCAPE 0x1B // keycode = 0x006e
#define KEY_MENUE 0x80 // keycode = 0x0070
#define KEY_BACK 0x81 // keycode = 0x0071
#define KEY_FORWARD 0x82 // keycode = 0x0072
#define KEY_ADDRESS 0x83 // keycode = 0x0073
#define KEY_WINDOW 0x84 // keycode = 0x0074
#define KEY_1ST_PAGE 0x85 // keycode = 0x0075
#define KEY_STOP 0x86 // keycode = 0x0076
#define KEY_MAIL 0x87 // keycode = 0x0077
#define KEY_FAVORITES 0x88 // keycode = 0x0078
#define KEY_NEW_PAGE 0x89 // keycode = 0x0079
#define KEY_SETUP 0x8A // keycode = 0x007a
#define KEY_FONT 0x8B // keycode = 0x007b
#define KEY_PRINT 0x8C // keycode = 0x007c
#define KEY_ON_OFF 0x8E // keycode = 0x007c
#define KEY_INSERT 0x90 // keycode = 0x004b
#define KEY_DELETE 0x91 // keycode = 0x004c
#define KEY_LEFT 0x92 // keycode = 0x004f
#define KEY_HOME 0x93 // keycode = 0x0050
#define KEY_END 0x94 // keycode = 0x0051
#define KEY_UP 0x95 // keycode = 0x0053
#define KEY_DOWN 0x96 // keycode = 0x0054
#define KEY_PAGE_UP 0x97 // keycode = 0x0055
#define KEY_PAGE_DOWN 0x98 // keycode = 0x0056
#define KEY_RIGHT 0x99 // keycode = 0x0059
#define KEY_MOUSE_1 0x9E // keycode = 0x0400
#define KEY_MOUSE_2 0x9F // keycode = 0x0800
static uint_fast8_t
get_fdc_key (uint_fast16_t cmd)
{
static const uint8_t key_table[128] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00, '^', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xDF, 0xB4, 0x00, '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0xFC, '+', 0x00, 0x00, 'a',
's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '#', '\r', 0x00, '<', 'y', 'x',
'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00,
0x00, 0xB0, '!', '"', 0xA7, '$', '%', '&', '/', '(', ')', '=', '?', 0x60, 0x00, '\b',
'\t', 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0xDC, '*', 0x00, 0x00, 'A',
'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, '\'', '\r', 0x00, '>', 'Y', 'X',
'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00
};
static uint_fast8_t state;
uint_fast8_t key = 0;
switch (cmd)
{
case 0x002C: state |= STATE_LEFT_SHIFT; break; // pressed left shift
case 0x00AC: state &= ~STATE_LEFT_SHIFT; break; // released left shift
case 0x0039: state |= STATE_RIGHT_SHIFT; break; // pressed right shift
case 0x00B9: state &= ~STATE_RIGHT_SHIFT; break; // released right shift
case 0x003A: state |= STATE_LEFT_CTRL; break; // pressed left ctrl
case 0x00BA: state &= ~STATE_LEFT_CTRL; break; // released left ctrl
case 0x003C: state |= STATE_LEFT_ALT; break; // pressed left alt
case 0x00BC: state &= ~STATE_LEFT_ALT; break; // released left alt
case 0x003E: state |= STATE_RIGHT_ALT; break; // pressed left alt
case 0x00BE: state &= ~STATE_RIGHT_ALT; break; // released left alt
case 0x006e: key = KEY_ESCAPE; break;
case 0x004b: key = KEY_INSERT; break;
case 0x004c: key = KEY_DELETE; break;
case 0x004f: key = KEY_LEFT; break;
case 0x0050: key = KEY_HOME; break;
case 0x0051: key = KEY_END; break;
case 0x0053: key = KEY_UP; break;
case 0x0054: key = KEY_DOWN; break;
case 0x0055: key = KEY_PAGE_UP; break;
case 0x0056: key = KEY_PAGE_DOWN; break;
case 0x0059: key = KEY_RIGHT; break;
case 0x0400: key = KEY_MOUSE_1; break;
case 0x0800: key = KEY_MOUSE_2; break;
default:
{
if (!(cmd & 0x80)) // pressed key
{
if (cmd >= 0x70 && cmd <= 0x7F) // function keys
{
key = cmd + 0x10; // 7x -> 8x
}
else if (cmd < 64) // key listed in key_table
{
if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT))
{
switch (cmd)
{
case 0x0003: key = 0xB2; break; // upper 2
case 0x0008: key = '{'; break;
case 0x0009: key = '['; break;
case 0x000A: key = ']'; break;
case 0x000B: key = '}'; break;
case 0x000C: key = '\\'; break;
case 0x001C: key = '~'; break;
case 0x002D: key = '|'; break;
case 0x0034: key = 0xB5; break; // Mu
}
}
else if (state & (STATE_LEFT_CTRL))
{
if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z')
{
key = key_table[cmd] - 'a' + 1;
}
else
{
key = key_table[cmd];
}
}
else
{
int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0);
if (key_table[idx])
{
key = key_table[idx];
}
}
}
}
break;
}
}
return (key);
}
static int analyze = FALSE;
static int list = FALSE;
static IRMP_DATA irmp_data;
static int expected_protocol;
static int expected_address;
static int expected_command;
static int do_check_expected_values;
static void
next_tick (void)
{
if (! analyze && ! list)
{
(void) irmp_ISR ();
if (irmp_get_data (&irmp_data))
{
uint_fast8_t key;
ANALYZE_ONLY_NORMAL_PUTCHAR (' ');
if (verbose)
{
printf ("%8.3fms ", (double) (time_counter * 1000) / F_INTERRUPTS);
}
if (irmp_data.protocol == IRMP_ACP24_PROTOCOL)
{
uint16_t temp = (irmp_data.command & 0x000F) + 15;
printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, temp=%d",
irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, temp);
}
else if (irmp_data.protocol == IRMP_FDC_PROTOCOL && (key = get_fdc_key (irmp_data.command)) != 0)
{
if ((key >= 0x20 && key < 0x7F) || key >= 0xA0)
{
printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key='%c'",
irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, key);
}
else if (key == '\r' || key == '\t' || key == KEY_ESCAPE || (key >= 0x80 && key <= 0x9F)) // function keys
{
const char * p = (const char *) nullptr;
switch (key)
{
case '\t' : p = "TAB"; break;
case '\r' : p = "CR"; break;
case KEY_ESCAPE : p = "ESCAPE"; break;
case KEY_MENUE : p = "MENUE"; break;
case KEY_BACK : p = "BACK"; break;
case KEY_FORWARD : p = "FORWARD"; break;
case KEY_ADDRESS : p = "ADDRESS"; break;
case KEY_WINDOW : p = "WINDOW"; break;
case KEY_1ST_PAGE : p = "1ST_PAGE"; break;
case KEY_STOP : p = "STOP"; break;
case KEY_MAIL : p = "MAIL"; break;
case KEY_FAVORITES : p = "FAVORITES"; break;
case KEY_NEW_PAGE : p = "NEW_PAGE"; break;
case KEY_SETUP : p = "SETUP"; break;
case KEY_FONT : p = "FONT"; break;
case KEY_PRINT : p = "PRINT"; break;
case KEY_ON_OFF : p = "ON_OFF"; break;
case KEY_INSERT : p = "INSERT"; break;
case KEY_DELETE : p = "DELETE"; break;
case KEY_LEFT : p = "LEFT"; break;
case KEY_HOME : p = "HOME"; break;
case KEY_END : p = "END"; break;
case KEY_UP : p = "UP"; break;
case KEY_DOWN : p = "DOWN"; break;
case KEY_PAGE_UP : p = "PAGE_UP"; break;
case KEY_PAGE_DOWN : p = "PAGE_DOWN"; break;
case KEY_RIGHT : p = "RIGHT"; break;
case KEY_MOUSE_1 : p = "KEY_MOUSE_1"; break;
case KEY_MOUSE_2 : p = "KEY_MOUSE_2"; break;
default : p = ""; break;
}
printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key=%s",
irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, p);
}
else
{
printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x",
irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key);
}
}
else
{
printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x",
irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags);
}
if (do_check_expected_values)
{
if (irmp_data.protocol != expected_protocol ||
irmp_data.address != expected_address ||
irmp_data.command != expected_command)
{
printf ("\nerror 7: expected values differ: p=%2d (%s), a=0x%04x, c=0x%04x\n",
expected_protocol, irmp_protocol_names[expected_protocol], expected_address, expected_command);
}
else
{
printf (" checked!\n");
}
do_check_expected_values = FALSE; // only check 1st frame in a line!
}
else
{
putchar ('\n');
}
}
}
}
int
main (int argc, char ** argv)
{
int i;
int ch;
int last_ch = 0;
int pulse = 0;
int pause = 0;
int start_pulses[256];
int start_pauses[256];
int pulses[256];
int pauses[256];
int first_pulse = TRUE;
int first_pause = TRUE;
if (argc == 2)
{
if (! strcmp (argv[1], "-v"))
{
verbose = TRUE;
}
else if (! strcmp (argv[1], "-l"))
{
list = TRUE;
}
else if (! strcmp (argv[1], "-a"))
{
analyze = TRUE;
}
else if (! strcmp (argv[1], "-s"))
{
silent = TRUE;
}
}
for (i = 0; i < 256; i++)
{
start_pulses[i] = 0;
start_pauses[i] = 0;
pulses[i] = 0;
pauses[i] = 0;
}
if (IRMP_HIGH_ACTIVE)
{
IRMP_PIN = 0x00;
}
else
{
IRMP_PIN = 0xFF;
}
while ((ch = getchar ()) != EOF)
{
if (ch == '_' || ch == '0')
{
if (last_ch != ch)
{
if (pause > 0)
{
if (list)
{
printf ("pause: %d\n", pause);
}
if (analyze)
{
if (first_pause)
{
if (pause < 256)
{
start_pauses[pause]++;
}
first_pause = FALSE;
}
else
{
if (pause < 256)
{
pauses[pause]++;
}
}
}
}
pause = 0;
}
pulse++;
if (IRMP_HIGH_ACTIVE)
{
IRMP_PIN = 0xff;
}
else
{
IRMP_PIN = 0x00;
}
}
else if (ch == 0xaf || ch == '-' || ch == '1')
{
if (last_ch != ch)
{
if (list)
{
printf ("pulse: %d ", pulse);
}
if (analyze)
{
if (first_pulse)
{
if (pulse < 256)
{
start_pulses[pulse]++;
}
first_pulse = FALSE;
}
else
{
if (pulse < 256)
{
pulses[pulse]++;
}
}
}
pulse = 0;
}
pause++;
if (IRMP_HIGH_ACTIVE)
{
IRMP_PIN = 0x00;
}
else
{
IRMP_PIN = 0xff;
}
}
else if (ch == '\n')
{
if (IRMP_HIGH_ACTIVE)
{
IRMP_PIN = 0x00;
}
else
{
IRMP_PIN = 0xff;
}
time_counter = 0;
if (list && pause > 0)
{
printf ("pause: %d\n", pause);
}
pause = 0;
if (! analyze)
{
for (i = 0; i < (int) ((10000.0 * F_INTERRUPTS) / 10000); i++) // newline: long pause of 10000 msec
{
next_tick ();
}
}
first_pulse = TRUE;
first_pause = TRUE;
}
else if (ch == '#')
{
time_counter = 0;
if (analyze)
{
while ((ch = getchar()) != '\n' && ch != EOF)
{
;
}
}
else
{
char buf[1024];
char * p;
int idx = -1;
puts ("----------------------------------------------------------------------");
putchar (ch);
while ((ch = getchar()) != '\n' && ch != EOF)
{
if (ch != '\r') // ignore CR in DOS/Windows files
{
if (ch == '[' && idx == -1)
{
idx = 0;
}
else if (idx >= 0)
{
if (ch == ']')
{
do_check_expected_values = FALSE;
buf[idx] = '\0';
idx = -1;
expected_protocol = atoi (buf);
if (expected_protocol > 0)
{
p = buf;
while (*p)
{
if (*p == 'x')
{
p++;
if (sscanf (p, "%x", &expected_address) == 1)
{
do_check_expected_values = TRUE;
}
break;
}
p++;
}
if (do_check_expected_values)
{
do_check_expected_values = FALSE;
while (*p)
{
if (*p == 'x')
{
p++;
if (sscanf (p, "%x", &expected_command) == 1)
{
do_check_expected_values = TRUE;
}
break;
}
p++;
}
if (do_check_expected_values)
{
// printf ("!%2d %04x %04x!\n", expected_protocol, expected_address, expected_command);
}
}
}
}
else if (idx < 1024 - 2)
{
buf[idx++] = ch;
}
}
putchar (ch);
}
}
putchar ('\n');
}
}
last_ch = ch;
next_tick ();
}
if (analyze)
{
print_spectrum ("START PULSES", start_pulses, TRUE);
print_spectrum ("START PAUSES", start_pauses, FALSE);
print_spectrum ("PULSES", pulses, TRUE);
print_spectrum ("PAUSES", pauses, FALSE);
puts ("-----------------------------------------------------------------------------");
}
return 0;
}
#endif // ANALYZE
================================================
FILE: src/irmpArduinoExt.h
================================================
/*
* irmpArduinoExt.h Arduino extensions to the original irmp.h
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#if defined(ARDUINO)
#ifndef _IRMP_ARDUINO_EXT_H
#define _IRMP_ARDUINO_EXT_H
#include // for Print
#include "irmpVersion.h"
#include "IRFeedbackLED.h" // for redefinition of
#include "digitalWriteFast.h" // we use pinModeFast() and digitalReadFast() and digitalWriteFast() in turn
/*
* For debugging purposes. The timing test pin for some platforms is specified in the PinDefinitionsAndMore.h files included in each example.
*/
//#define IRMP_MEASURE_TIMING
//#define IR_TIMING_TEST_PIN
//
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Enable dynamic pin configuration in contrast to the static one which is known at compile time and saves program memory and CPU cycles.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
//#define IRMP_IRSND_ALLOW_DYNAMIC_PINS
//
//
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Enable PinChangeInterrupt add on for irmp_ISR(). Tested for NEC, Kaseiko, Denon, RC6 protocols and Arduino Uno and Arduino ATmega.
* Receives IR protocol data by using pin change interrupts and no polling by timer.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT
#if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
# if ! (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \
&& ! ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IRMP_INPUT_PIN == 3) || (IRMP_INPUT_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\
|| (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IRMP_INPUT_PIN == 3) || (IRMP_INPUT_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \
&& ! ( ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
|| defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
|| defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)) \
&& ((IRMP_INPUT_PIN == 2) || (IRMP_INPUT_PIN == 3)) ) /* ATmegas and pin 2 or 3 */
# define IRMP_USE_ARDUINO_ATTACH_INTERRUPT // cannot use any static ISR vector here
# endif
# undef F_INTERRUPTS
# define F_INTERRUPTS 15625 // 15625 interrupts per second gives 64 us period
#endif
#if defined(__AVR__)
#define uint_fast8_t uint8_t
#define uint_fast16_t uint16_t
#elif defined(ESP8266)
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "c_types.h"
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3
#include "mbed.h"
#elif defined(ESP32)
#elif defined(STM32F1xx) // for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager
#elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx
#elif defined(__STM32F1__) // for "Generic STM32F103C series" from "STM32F1 Boards (STM32duino.com)" of Arduino Board manager
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for Arduino IDE if no IRMP_INPUT_PIN specified
* Should be first, since it covers multiple platforms
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
extern uint_fast8_t irmp_InputPin; // global variable to hold input pin number. Is referenced by defining IRMP_INPUT_PIN as irmp_InputPin.
#undef IRMP_INPUT_PIN
#define IRMP_INPUT_PIN irmp_InputPin
#else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
# if !defined(IRMP_INPUT_PIN) // Arduino IDE uses IRMP_INPUT_PIN instead of PORT and BIT
#define IRMP_INPUT_PIN 2
# endif
#endif
#if defined(IRMP_INPUT_PIN)
# if defined(__AVR__)
# define input(x) (__builtin_constant_p(IRMP_INPUT_PIN) ) ? digitalReadFast(IRMP_INPUT_PIN) : digitalRead(IRMP_INPUT_PIN)
# else
# define input(x) digitalRead(IRMP_INPUT_PIN)
# endif
#endif
#if !defined(IR_TIMING_TEST_PIN) // Only for test purposes
#define IR_TIMING_TEST_PIN 5
#endif
void irmp_init(uint_fast8_t aIrmpInputPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);
bool irmp_IsBusy();
extern uint32_t irmp_last_change_micros;
void irmp_result_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr);
void irmp_result_print(IRMP_DATA *aIRMPDataPtr);
void irmp_PCI_ISR(void);
void enablePCIInterrupt(void);
void disablePCIInterrupt(void);
void irmp_print_active_protocols(Print *aSerial);
void irmp_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber);
extern const uint8_t irmp_used_protocol_index[] PROGMEM;
extern const char *const irmp_used_protocol_names[] PROGMEM;
#endif // _IRMP_ARDUINO_EXT_H
#endif // ARDUINO
================================================
FILE: src/irmpArduinoExt.hpp
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpArduinoExt.hpp - Arduino extensions to the original irmp.c
*
* Copyright (c) 2019-2020 Armin Joachimsmeyer
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// // Must be included after declaration of irmp_start_bit_detected etc.
#if defined(ARDUINO)
#undef _IRSND_H_ // We are in IRMP now! Remove old symbol maybe set from former including irsnd.hpp.
#include "IRTimer.hpp" // include code for timer
#include "IRFeedbackLED.hpp" // include code for Feedback LED
#include "irmpprotocols.hpp" // include protocol strings and array of strings
#if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
#include "irmpPinChangeInterrupt.hpp"
#endif // defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
uint_fast8_t irmp_InputPin; // global variable to hold input pin number. Is referenced by defining IRMP_INPUT_PIN as irmp_InputPin.
/*
* Initialize, and activate feedback LED function
*/
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow)
{
irmp_InputPin = aIrmpInputPin;
#if !defined(NO_LED_FEEDBACK_CODE)
irmp_irsnd_LedFeedbackPin = aFeedbackLedPin;
irmp_irsnd_LedFeedbackPinIsActiveLow = aIrmpLedFeedbackPinIsActiveLow;
/*
* enable feedback LED if (aFeedbackLedPin != 0)
*/
irmp_irsnd_LEDFeedback(aFeedbackLedPin);
#else
(void) aFeedbackLedPin; // to avoid compiler warnings
(void) aIrmpLedFeedbackPinIsActiveLow; // to avoid compiler warnings
#endif
# if defined IRMP_ENABLE_PIN_CHANGE_INTERRUPT
enablePCIInterrupt();
# else
initIRTimerForReceive();
# endif
# if defined(IRMP_MEASURE_TIMING)
pinModeFast(IR_TIMING_TEST_PIN, OUTPUT);
# endif
}
/*
* Initialize, and activate feedback LED function
* @param irmp_irsnd_LedFeedbackPin if 0 feedback led is not activated
*/
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin)
{
#if defined(NO_LED_FEEDBACK_CODE)
irmp_init(aIrmpInputPin, aFeedbackLedPin, false);
#else
irmp_init(aIrmpInputPin, aFeedbackLedPin, irmp_irsnd_LedFeedbackPinIsActiveLow);
#endif
}
/*
* Initialize, but do not activate feedback LED by default, using irmp_irsnd_LedFeedbackPin as led pin.
*/
void irmp_init(uint_fast8_t aIrmpInputPin)
{
#if defined(NO_LED_FEEDBACK_CODE)
irmp_init(aIrmpInputPin, 0, false);
#else
irmp_init(aIrmpInputPin, irmp_irsnd_LedFeedbackPin, irmp_irsnd_LedFeedbackPinIsActiveLow);
#endif
# if defined(IRMP_FEEDBACK_LED_PIN)
// set pin if we have one at hand
irmp_irsnd_LedFeedbackPin = IRMP_FEEDBACK_LED_PIN;
# endif
}
#endif // if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
void irmp_init(void)
{
# if defined(IRMP_INPUT_PIN)
pinModeFast(IRMP_INPUT_PIN, INPUT); // set pin to input
# else
IRMP_PORT &= ~_BV(IRMP_BIT); // deactivate pullup
IRMP_DDR &= ~_BV(IRMP_BIT);// set pin to input
# endif
# if defined IRMP_ENABLE_PIN_CHANGE_INTERRUPT
enablePCIInterrupt();
# else
initIRTimerForReceive();
# endif
# if defined(IRMP_MEASURE_TIMING)
pinModeFast(IR_TIMING_TEST_PIN, OUTPUT);
# endif
}
/*
* Called from the receiver ISR IRMP_ISR() with the raw input value. Receiver signal input is active low!
* With -oS it is taken as inline function
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR irmp_DoLEDFeedback(bool aSwitchLedOff)
#else
void irmp_DoLEDFeedback(bool aSwitchLedOff)
#endif
{
#if !defined(NO_LED_FEEDBACK_CODE)
if (irmp_irsnd_LedFeedbackEnabled)
{
irmp_irsnd_SetFeedbackLED(!aSwitchLedOff);
}
#else
(void) aSwitchLedOff; // to avoid compiler warnings
#endif
}
/*
* returns true, if there is an ongoing transmission or repetition
*/
bool irmp_IsBusy()
{
#if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT)
uint32_t tTicks = micros() - irmp_last_change_micros;
tTicks = (tTicks << 2) >> 8;
return (irmp_start_bit_detected || irmp_pulse_time || tTicks <= IRMP_KEY_REPETITION_LEN);
#else
return (irmp_start_bit_detected || irmp_pulse_time || key_repetition_len <= IRMP_KEY_REPETITION_LEN);
#endif
}
/*
* irmp_used_protocol_index holds the protocol numbers (from irmpprotocols.h)
* for the included protocol name entries of the irmp_used_protocol_names array below
* E.g. irmp_used_protocol_index=2,7 and irmp_used_protocol_names="NEC","RC5".
*
* Both arrays together are generally smaller than the complete irmp_protocol_names array
* allowing them to be used on ATtinies even if program code for access is bigger.
* Flash size is more than 100 bytes less (for 15 protocols) using these arrays.
*/
const uint8_t irmp_used_protocol_index[] PROGMEM =
{
IRMP_UNKNOWN_PROTOCOL,
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
IRMP_SIRCS_PROTOCOL,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
IRMP_NEC_PROTOCOL,
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
IRMP_SAMSUNG_PROTOCOL,
#endif
#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1
IRMP_MATSUSHITA_PROTOCOL,
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
IRMP_KASEIKYO_PROTOCOL,
#endif
#if IRMP_SUPPORT_RECS80_PROTOCOL == 1
IRMP_RECS80_PROTOCOL,
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
IRMP_RC5_PROTOCOL,
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
IRMP_DENON_PROTOCOL,
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
IRMP_RC6_PROTOCOL,
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
IRMP_SAMSUNG32_PROTOCOL,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
IRMP_APPLE_PROTOCOL,
#endif
#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1
IRMP_RECS80EXT_PROTOCOL,
#endif
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1
IRMP_NUBERT_PROTOCOL,
#endif
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
IRMP_BANG_OLUFSEN_PROTOCOL,
#endif
#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1
IRMP_GRUNDIG_PROTOCOL,
#endif
#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1
IRMP_NOKIA_PROTOCOL,
#endif
#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1
IRMP_SIEMENS_PROTOCOL,
#endif
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
IRMP_FDC_PROTOCOL,
#endif
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
IRMP_RCCAR_PROTOCOL,
#endif
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
IRMP_JVC_PROTOCOL,
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
IRMP_RC6A_PROTOCOL,
#endif
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
IRMP_NIKON_PROTOCOL,
#endif
#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1
IRMP_RUWIDO_PROTOCOL,
#endif
#if IRMP_SUPPORT_IR60_PROTOCOL == 1
IRMP_IR60_PROTOCOL,
#endif
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
IRMP_KATHREIN_PROTOCOL,
#endif
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1
IRMP_NETBOX_PROTOCOL,
#endif
#if IRMP_SUPPORT_NEC16_PROTOCOL == 1
IRMP_NEC16_PROTOCOL,
#endif
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
IRMP_NEC42_PROTOCOL,
#endif
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1
IRMP_LEGO_PROTOCOL,
#endif
#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1
IRMP_THOMSON_PROTOCOL,
#endif
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1
IRMP_BOSE_PROTOCOL,
#endif
#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1
IRMP_A1TVBOX_PROTOCOL,
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
IRMP_ORTEK_PROTOCOL,
#endif
#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
IRMP_TELEFUNKEN_PROTOCOL,
#endif
#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
IRMP_ROOMBA_PROTOCOL,
#endif
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
IRMP_RCMM32_PROTOCOL,
IRMP_RCMM24_PROTOCOL,
IRMP_RCMM12_PROTOCOL,
#endif
#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
IRMP_SPEAKER_PROTOCOL,
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
IRMP_LGAIR_PROTOCOL,
#endif
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
IRMP_SAMSUNG48_PROTOCOL,
#endif
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
IRMP_MERLIN_PROTOCOL,
#endif
#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1
IRMP_PENTAX_PROTOCOL,
#endif
#if IRMP_SUPPORT_FAN_PROTOCOL == 1
IRMP_FAN_PROTOCOL,
#endif
#if IRMP_SUPPORT_S100_PROTOCOL == 1
IRMP_S100_PROTOCOL,
#endif
#if IRMP_SUPPORT_ACP24_PROTOCOL == 1
IRMP_ACP24_PROTOCOL,
#endif
#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1
IRMP_TECHNICS_PROTOCOL,
#endif
#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 || IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // Panasonic vendor ID for kaseikyo
IRMP_PANASONIC_PROTOCOL,
#endif
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
IRMP_MITSU_HEAVY_PROTOCOL,
#endif
#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1
IRMP_VINCENT_PROTOCOL,
#endif
#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1
IRMP_SAMSUNGAH_PROTOCOL,
#endif
#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1
IRMP_IRMP16_PROTOCOL,
#endif
#if IRMP_SUPPORT_GREE_PROTOCOL == 1
IRMP_GREE_PROTOCOL,
#endif
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
IRMP_RCII_PROTOCOL,
#endif
#if IRMP_SUPPORT_METZ_PROTOCOL == 1
IRMP_METZ_PROTOCOL,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
IRMP_ONKYO_PROTOCOL,
#endif
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
RF_GEN24_PROTOCOL,
#endif
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1
RF_X10_PROTOCOL,
#endif
#if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
RF_MEDION_PROTOCOL
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
IRMP_MELINERA_PROTOCOL
#endif
#if IRMP_SUPPORT_RC6A20_PROTOCOL == 1
IRMP_RC6A20_PROTOCOL
#endif
#if IRMP_SUPPORT_RC6A28_PROTOCOL == 1
IRMP_RC6A28_PROTOCOL
#endif
};
const char * const irmp_used_protocol_names[] PROGMEM =
{
proto_unknown,
#if IRMP_SUPPORT_SIRCS_PROTOCOL == 1
proto_sircs,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
proto_nec,
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
proto_samsung,
#endif
#if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1
proto_matsushita,
#endif
#if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1
proto_kaseikyo,
#endif
#if IRMP_SUPPORT_RECS80_PROTOCOL == 1
proto_recs80,
#endif
#if IRMP_SUPPORT_RC5_PROTOCOL == 1
proto_rc5,
#endif
#if IRMP_SUPPORT_DENON_PROTOCOL == 1
proto_denon,
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
proto_rc6,
#endif
#if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1
proto_samsung32,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
proto_apple,
#endif
#if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1
proto_recs80ext,
#endif
#if IRMP_SUPPORT_NUBERT_PROTOCOL == 1
proto_nubert,
#endif
#if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
proto_bang_olufsen,
#endif
#if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1
proto_grundig,
#endif
#if IRMP_SUPPORT_NOKIA_PROTOCOL == 1
proto_nokia,
#endif
#if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1
proto_siemens,
#endif
#if IRMP_SUPPORT_FDC_PROTOCOL == 1
proto_fdc,
#endif
#if IRMP_SUPPORT_RCCAR_PROTOCOL == 1
proto_rccar,
#endif
#if IRMP_SUPPORT_JVC_PROTOCOL == 1
proto_jvc,
#endif
#if IRMP_SUPPORT_RC6_PROTOCOL == 1
proto_rc6a,
#endif
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
proto_nikon,
#endif
#if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1
proto_ruwido,
#endif
#if IRMP_SUPPORT_IR60_PROTOCOL == 1
proto_ir60,
#endif
#if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1
proto_kathrein,
#endif
#if IRMP_SUPPORT_NETBOX_PROTOCOL == 1
proto_netbox,
#endif
#if IRMP_SUPPORT_NEC16_PROTOCOL == 1
proto_nec16,
#endif
#if IRMP_SUPPORT_NEC42_PROTOCOL == 1
proto_nec42,
#endif
#if IRMP_SUPPORT_LEGO_PROTOCOL == 1
proto_lego,
#endif
#if IRMP_SUPPORT_THOMSON_PROTOCOL == 1
proto_thomson,
#endif
#if IRMP_SUPPORT_BOSE_PROTOCOL == 1
proto_bose,
#endif
#if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1
proto_a1tvbox,
#endif
#if IRMP_SUPPORT_ORTEK_PROTOCOL == 1
proto_ortek,
#endif
#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
proto_telefunken,
#endif
#if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1
proto_roomba,
#endif
#if IRMP_SUPPORT_RCMM_PROTOCOL == 1
proto_rcmm32,
proto_rcmm24,
proto_rcmm12,
#endif
#if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1
proto_speaker,
#endif
#if IRMP_SUPPORT_LGAIR_PROTOCOL == 1
proto_lgair,
#endif
#if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1
proto_samsung48,
#endif
#if IRMP_SUPPORT_MERLIN_PROTOCOL == 1
proto_merlin,
#endif
#if IRMP_SUPPORT_PENTAX_PROTOCOL == 1
proto_pentax,
#endif
#if IRMP_SUPPORT_FAN_PROTOCOL == 1
proto_fan,
#endif
#if IRMP_SUPPORT_S100_PROTOCOL == 1
proto_s100,
#endif
#if IRMP_SUPPORT_ACP24_PROTOCOL == 1
proto_acp24,
#endif
#if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1
proto_technics,
#endif
#if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 || IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // Panasonic vendor ID for kaseikyo
proto_panasonic,
#endif
#if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
proto_mitsu_heavy,
#endif
#if IRMP_SUPPORT_VINCENT_PROTOCOL == 1
proto_vincent,
#endif
#if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1
proto_samsungah,
#endif
#if IRMP_SUPPORT_IRMP16_PROTOCOL == 1
proto_irmp16,
#endif
#if IRMP_SUPPORT_GREE_PROTOCOL == 1
proto_gree,
#endif
#if IRMP_SUPPORT_RCII_PROTOCOL == 1
proto_rcii,
#endif
#if IRMP_SUPPORT_METZ_PROTOCOL == 1
proto_metz,
#endif
#if IRMP_SUPPORT_NEC_PROTOCOL == 1
proto_onkyo,
#endif
#if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1
proto_rf_gen24,
#endif
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1
proto_rf_x10,
#endif
#if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
proto_rf_medion
#endif
#if IRMP_SUPPORT_MELINERA_PROTOCOL == 1
proto_melinera
#endif
#if IRMP_SUPPORT_RC6A20_PROTOCOL == 1
proto_rc6a20
#endif
#if IRMP_SUPPORT_RC6A28_PROTOCOL == 1
proto_rc6a28
#endif
};
/*
* No newline after printing
*/
void irmp_print_active_protocols(Print *aSerial)
{
// skip protocol 0 = UNKNOWN
for (uint_fast8_t i = 1; i < sizeof(irmp_used_protocol_index); ++i)
{
#if IRMP_PROTOCOL_NAMES == 1
/*
* Read names of protocol from array and print
*/
# if defined(__AVR__)
const char* tProtocolStringPtr = (char*) pgm_read_word(&irmp_used_protocol_names[i]);
aSerial->print((__FlashStringHelper *) (tProtocolStringPtr));
# else
aSerial->print(irmp_used_protocol_names[i]);
# endif
#else
/*
* Print just numbers of the protocols not the names
*/
# if defined(__AVR__)
uint8_t tProtocolNumber = (uint8_t) pgm_read_byte(&irmp_used_protocol_index[i]);
aSerial->print(tProtocolNumber);
# else
aSerial->print(irmp_used_protocol_index[i]);
# endif
#endif
aSerial->print(", ");
}
}
void irmp_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber)
{
#if IRMP_PROTOCOL_NAMES == 1
# if defined(__AVR__)
for (uint_fast8_t i = 0; i < sizeof(irmp_used_protocol_index); ++i)
{
if(pgm_read_byte(&irmp_used_protocol_index[i]) == aProtocolNumber)
{
const char* tProtocolStringPtr = (char*) pgm_read_word(&irmp_used_protocol_names[i]);
aSerial->print((__FlashStringHelper *) (tProtocolStringPtr));
return;
}
}
# else
// no need to save space
aSerial->print(irmp_protocol_names[aProtocolNumber]);
# endif
#endif
// append protocol number
aSerial->print(F(" | 0x"));
aSerial->print(aProtocolNumber, HEX);
}
/*
* Print protocol name or number, address, code and repetition flag
* needs appr. 2 milliseconds for output
*/
void irmp_result_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr)
{
/*
* Print protocol name or number
*/
aSerial->print(F("P="));
irmp_print_protocol_name(aSerial, aIRMPDataPtr->protocol);
/*
* Print address, code and repetition flag
*/
aSerial->print(F(" A=0x"));
aSerial->print(aIRMPDataPtr->address, HEX);
aSerial->print(F(" C=0x"));
aSerial->print(aIRMPDataPtr->command, HEX);
if (aIRMPDataPtr->flags & IRMP_FLAG_REPETITION)
{
aSerial->print(F(" R"));
}
aSerial->println();
}
/*
* Do not just call irmp_result_print( &Serial, aIRMPDataPtr) above, since this is not always possible for ATtinies.
*/
void irmp_result_print(IRMP_DATA *aIRMPDataPtr)
{
/*
* Print protocol name or number
*/
Serial.print(F("P="));
// Wee need to check if &Serial is of type Print in order not to get errors on e.g. ATtinies
// This is not the exact right condition, but on ATtinies you will mostly disable protocol names
#if IRMP_PROTOCOL_NAMES == 1
irmp_print_protocol_name(&Serial, aIRMPDataPtr->protocol);
#else
Serial.print(F("0x"));
Serial.print(aIRMPDataPtr->protocol, HEX);
#endif
/*
* Print address, code and repetition flag
*/
Serial.print(F(" A=0x"));
Serial.print(aIRMPDataPtr->address, HEX);
Serial.print(F(" C=0x"));
Serial.print(aIRMPDataPtr->command, HEX);
if (aIRMPDataPtr->flags & IRMP_FLAG_REPETITION)
{
Serial.print(F(" R"));
}
Serial.println();
}
#endif // defined(ARDUINO)
================================================
FILE: src/irmpPinChangeInterrupt.hpp
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpPinChangeInterrupt.hpp
*
* Functions and ISR for the pin change interrupt functionality for IRMP - For Arduino platform
* Must be included after irmp_ISR to have all the internal variables of irmp_ISR declared
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef _IRMP_PIN_CHANGE_INTERRUPT_HPP
#define _IRMP_PIN_CHANGE_INTERRUPT_HPP
//#define PCI_DEBUG
# if defined(__AVR__)
void irmp_debug_print(const __FlashStringHelper *aMessage, bool aDoShortOutput = true);
# else
void irmp_debug_print(const char *aMessage, bool aDoShortOutput);
# endif
uint32_t irmp_last_change_micros; // microseconds of last Pin Change Interrupt. Used for irmp_IsBusy().
/*
* Wrapper for irmp_ISR() in order to run it with Pin Change Interrupts.
* Needs additional 8-9us per call and 13us for signal going inactive and 19us for going active.
* Tested for NEC, Kaseiko, Denon, RC6, Samsung and others.
* Requires micros() for timing.
*/
//#define PCI_DEBUG
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR irmp_PCI_ISR(void)
#else
void irmp_PCI_ISR(void)
#endif
{
// save IR input level - negative logic, true means inactive / IR pause
uint_fast8_t irmp_input = input(IRMP_PIN);
/*
* 1. compute ticks after last change
*/
uint32_t tMicros = micros();
uint32_t tTicks = tMicros - irmp_last_change_micros; // values up to 10000
irmp_last_change_micros = tMicros;
#if (F_INTERRUPTS == 15625)
// F_INTERRUPTS value of 31250 does not work (maybe 8 bit overflow?)
tTicks = (tTicks << 2) >> 8;// saves 1.3 us
#else
#error F_INTERRUPTS must be 15625 (to avoid a time consuming division)
#endif
if (tTicks != 0) {
tTicks -= 1; // adjust for irmp_pulse_time / irmp_pause_time incremented in irmp_ISR()
}
/*
* 2. check for input level and tweak timings
*/
if (irmp_input) // true means inactive / IR pause
{
// start of pause -> just set pulse width
irmp_pulse_time += tTicks;
} else {
if (irmp_start_bit_detected) {
irmp_pause_time += tTicks;
} else { // start pulse here -> set pause or time between repetitions
if (tTicks > UINT16_MAX) {
// avoid overflow for 16 bit key_repetition_len
tTicks = UINT16_MAX;
}
key_repetition_len = tTicks;
}
}
/*
* 3. call the protocol detection routine
*/
irmp_ISR();
if (!irmp_ir_detected && irmp_input) {
/*
* No valid protocol detected and IR input is inactive now -> simulate end for protocols.
* IRMP may be waiting for stop bit, but detects it only at the next call, so do one additional call.
* !!! ATTENTION !!! This will NOT work if we try to receive simultaneously two protocols which are only different in length like NEC16 and NEC42
*/
#if defined(PCI_DEBUG)
Serial.write('x');
if (irmp_bit > 0 && irmp_bit == irmp_param.complete_len)
{
Serial.println(irmp_start_bit_detected); // print start bit if complete_len is reached
}
#endif
if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == TRUE) {
// Try to detect a nec repeat irmp_bit is 0
#if defined(PCI_DEBUG)
irmp_debug_print(F("R"));
#endif
PAUSE_LEN irmp_pause_time_store = irmp_pause_time;
irmp_pause_time = STOP_BIT_PAUSE_LEN_MIN + 1; // set pause time to minimal pause required to detect a stop bit
irmp_ISR(); // Call to detect a NEC repeat
#if defined(PCI_DEBUG)
irmp_debug_print(F("E")); // print info after call
Serial.println();
#endif
if (irmp_ir_detected) {
// no protocol detected -> restore irmp_pause_time. Not sure if this is really required.
irmp_pause_time = irmp_pause_time_store;
}
}
// For condition see also line 4203 and 5098 in irmp.hpp
if (irmp_start_bit_detected && irmp_bit > 0 && irmp_bit == irmp_param.complete_len) {
// Complete length of bit now received -> try to detect end of protocol
#if defined(PCI_DEBUG)
irmp_debug_print(F("S")); // print info before call
#endif
PAUSE_LEN irmp_pause_time_store = irmp_pause_time;
irmp_pause_time = STOP_BIT_PAUSE_LEN_MIN + 1; // set pause time to minimal pause required to detect a stop bit
irmp_ISR(); // Call to detect end of protocol, irmp_param.stop_bit (printed as Sb) should be set to 0 if stop bit was successfully detected.
#if defined(PCI_DEBUG)
irmp_debug_print(F("E")); // print info after call
Serial.println();
#endif
if (irmp_ir_detected) {
// no protocol detected -> restore irmp_pause_time. Not sure if this is really required.
irmp_pause_time = irmp_pause_time_store;
}
}
#if (IRMP_SUPPORT_MANCHESTER == 1)
/*
* Simulate end for Manchester/biphase protocols - 130 bytes
*/
if (((irmp_bit == irmp_param.complete_len - 1 && tTicks < irmp_param.pause_1_len_max)
|| (irmp_bit == irmp_param.complete_len - 2 && tTicks > irmp_param.pause_1_len_max))
&& (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && irmp_start_bit_detected)
{
# if defined(PCI_DEBUG)
Serial.println('M'); // Try to detect a Manchester end of protocol
# endif
irmp_pause_time = 2 * irmp_param.pause_1_len_max;
irmp_ISR(); // Write last one (with value 0) or 2 (with last value 1) data bits and set wait for dummy stop bit
irmp_ISR();// process dummy stop bit
irmp_ISR();// reset stop bit and call callback
}
#endif
}
}
void enablePCIInterrupt() {
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
attachInterrupt(IRMP_INPUT_PIN, irmp_PCI_ISR, CHANGE); // 14.2 us before LED Feedback compared to 12 if configured with macros and less compatible
#elif ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
# if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
attachInterrupt(IRMP_INPUT_PIN, irmp_PCI_ISR, CHANGE);
# else
attachInterrupt(digitalPinToInterrupt(IRMP_INPUT_PIN), irmp_PCI_ISR, CHANGE); // CHANGE can be an enum :-(
# endif
#else
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// use PinChangeInterrupt
PCMSK |= _BV(IRMP_INPUT_PIN);
// clear interrupt bit
GIFR |= 1 << PCIF;
// enable interrupt on next change
GIMSK |= 1 << PCIE;
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IRMP_INPUT_PIN == 3)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IRMP_INPUT_PIN == 9)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 9 or 3."
# endif // if (IRMP_INPUT_PIN == 9)
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IRMP_INPUT_PIN == 14)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IRMP_INPUT_PIN == 3)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 14 or 3."
# endif // if (IRMP_INPUT_PIN == 14)
# endif
# else // defined(__AVR_ATtiny25__)
/*
* ATmegas here
*/
# if (IRMP_INPUT_PIN == 2)
// interrupt on any logical change
EICRA |= _BV(ISC00);
// clear interrupt bit
EIFR |= 1 << INTF0;
// enable interrupt on next change
EIMSK |= 1 << INT0;
# elif (IRMP_INPUT_PIN == 3)
EICRA |= _BV(ISC10);
// clear interrupt bit
EIFR |= 1 << INTF1;
// enable interrupt on next change
EIMSK |= 1 << INT1;
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 2 or 3."
# endif // if (IRMP_INPUT_PIN == 2)
# endif // defined(__AVR_ATtiny25__)
#endif // ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
}
void disablePCIInterrupt() {
#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
detachInterrupt(IRMP_INPUT_PIN);
#elif ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
detachInterrupt(digitalPinToInterrupt(IRMP_INPUT_PIN));
#else
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// clear interrupt bit
GIFR |= 1 << PCIF;
// disable interrupt on next change
GIMSK &= ~(1 << PCIE);
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IRMP_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~( 1 << INT0);
# elif (IRMP_INPUT_PIN == 9)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 9 or 3."
# endif // if (IRMP_INPUT_PIN == 9)
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
# if (IRMP_INPUT_PIN == 14)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~(1 << INT0);
# elif (IRMP_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 14 or 3."
# endif // if (IRMP_INPUT_PIN == 14)
# endif
# else // defined(__AVR_ATtiny25__)
/*
* ATmegas here
*/
# if (IRMP_INPUT_PIN == 2)
// clear interrupt bit
EIFR |= 1 << INTF0;
// disable interrupt on next change
EIMSK &= ~(1 << INT0);
# elif (IRMP_INPUT_PIN == 3)
// clear interrupt bit
EIFR |= 1 << INTF1;
// disable interrupt on next change
EIMSK &= ~(1 << INT1);
# else
# error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 2 or 3."
# endif // if (IRMP_INPUT_PIN == 2)
# endif // defined(__AVR_ATtiny25__)
#endif // ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
}
/*
* Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores
*/
#if defined(__AVR__) && !defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
# if (IRMP_INPUT_PIN == 2)
ISR(INT0_vect) // Pin 2 global assignment
# elif (IRMP_INPUT_PIN == 3)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
ISR(INT0_vect) // Pin 3 / PB6 / INT0 is connected to USB+ on DigisparkPro boards
# else
ISR(INT1_vect) // Pin 3 global assignment
# endif
# elif (IRMP_INPUT_PIN == 9) // Digispark pro
ISR(INT1_vect)
# elif (IRMP_INPUT_PIN == 14) // For AVR_ATtiny167 INT0 is on pin 14 / PB6
ISR(INT0_vect)
# elif (! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
ISR(PCINT0_vect)
# endif // (IRMP_INPUT_PIN == 2)
{
irmp_PCI_ISR();
}
#endif // defined(__AVR__) && !defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT)
#if defined(__AVR__)
void irmp_debug_print(const __FlashStringHelper *aMessage, bool aDoShortOutput)
#else
void irmp_debug_print(const char *aMessage, bool aDoShortOutput)
#endif
{
Serial.print(aMessage);
Serial.print(' ');
Serial.print(irmp_ir_detected); // valid IR command detected
Serial.print(F(" St"));
Serial.print(irmp_start_bit_detected);
Serial.print(F(" Ws"));
Serial.print(wait_for_space); // true if in data/address section and no signal. Now increment pause time.
Serial.print(F(" Wss"));
Serial.print(wait_for_start_space); // true if we have received start bit
Serial.print(F(" L"));
Serial.print(irmp_param.complete_len); // maximum bit position
Serial.print(F(" B"));
Serial.print((int8_t) irmp_bit); // current bit position - FF(-1) is start value
Serial.print(F(" Pu"));
Serial.print(irmp_pulse_time); // bit time for pulse
Serial.print(F(" Pa"));
Serial.print(irmp_pause_time);
Serial.print(F(" Sb"));
Serial.print(irmp_param.stop_bit); // boolean. 1 = stop bit required
if (!aDoShortOutput)
{
Serial.print(F(" F"));
Serial.print(irmp_flags); // currently only repetition flag
Serial.print(F(" K"));
Serial.print(key_repetition_len); // the pause after a command to distinguish repetitions from new commands
Serial.print(F(" R"));
Serial.print(repetition_frame_number); // Number of repetitions
}
Serial.println();
}
#endif // _IRMP_PIN_CHANGE_INTERRUPT_HPP
================================================
FILE: src/irmpSelectAllProtocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpSelectAllProtocols.h
* 42 + 1 protocols enabled
* 8 Protocols disabled since they conflicts with the enabled ones
* Depending on the value of F_INTERRUPTS 2 other protocols (LEGO and RCMM or PENTAX and GREE) are disabled too - see F_INTERRUPTS below
*
*
* Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_SELECT_PROTOCOLS_H
#define _IRMP_SELECT_PROTOCOLS_H
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more decoders.
* This saves program memory.
*
* 1 enable decoder
* 0 disable decoder
*
* The standard decoders are enabled per default.
* Less common protocols are disabled here, you need to enable them manually.
*
* If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required.
* If you don't need RC5 when using FDC/RCCAR, you should disable RC5.
* You cannot enable both DENON and RUWIDO, only enable one of them.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 1: IR decoders
* If you use a RF receiver, deactivate all IR protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// 4 typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes
// 11 more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL 1 // IR60 (SDA2008) >= 10000 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens Gigaset >= 15000 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~300 bytes
// 27 + 8 exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_BOSE_PROTOCOL 1 // BOSE >= 10000 ~150 bytes
#define IRMP_SUPPORT_KATHREIN_PROTOCOL 1 // Kathrein >= 10000 ~200 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL 1 // NUBERT >= 10000 ~50 bytes
#define IRMP_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~50 bytes conflicts with NUBERT
#define IRMP_SUPPORT_SPEAKER_PROTOCOL 1 // SPEAKER (~NUBERT) >= 10000 ~50 bytes
#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 1 // Bang & Olufsen >= 10000 ~200 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL 1 // RECS80 (SAA3004) >= 15000 ~50 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 1 // RECS80EXT (SAA3008) >= 15000 ~50 bytes
#define IRMP_SUPPORT_THOMSON_PROTOCOL 1 // Thomson >= 10000 ~250 bytes
#define IRMP_SUPPORT_NIKON_PROTOCOL 1 // NIKON camera >= 10000 ~250 bytes
#define IRMP_SUPPORT_NETBOX_PROTOCOL 1 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!)
#define IRMP_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 ~150 bytes conflicts with FDC and NETBOX
#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 1 // Telefunken 1560 >= 10000 ~150 bytes
#define IRMP_SUPPORT_FDC_PROTOCOL 1 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5)
#define IRMP_SUPPORT_RCCAR_PROTOCOL 1 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5)
#define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes conflicts with RC6
#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes conflicts with DENON
#define IRMP_SUPPORT_A1TVBOX_PROTOCOL 1 // A1 TV BOX >= 15000 (better 20000) ~300 bytes
#define IRMP_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes
#define IRMP_SUPPORT_RCMM_PROTOCOL 1 // RCMM 12,24, or 32 >= 20000 ~150 bytes
#define IRMP_SUPPORT_LGAIR_PROTOCOL 1 // LG Air Condition >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 1 // Samsung48 >= 10000 ~100 bytes (SAMSUNG must be enabled!)
#define IRMP_SUPPORT_MERLIN_PROTOCOL 1 // Merlin >= 15000 (better 20000) ~300 bytes (requires IRMP_32_BIT=1)
#define IRMP_SUPPORT_PENTAX_PROTOCOL 1 // Pentax >= 10000 <=17000 ~150 bytes (<= 17000 due to 8 bit timing overflow issue)
#define IRMP_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 ~250 bytes conflicts with RC5
#define IRMP_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~250 bytes conflicts with DENON
#define IRMP_SUPPORT_TECHNICS_PROTOCOL 1 // TECHNICS >= 10000 ~250 bytes
#define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~250 bytes Panasonic is Kaseikyo with vendor code 0x2002 and you cannot distinguish it by start bit timing.
#define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi Aircond >= 10000 ~250 bytes Mitsubishi is Kaseikyo with vendor code 0xCB23 and you cannot distinguish it by start bit timing.
#define IRMP_SUPPORT_VINCENT_PROTOCOL 1 // VINCENT >= 10000 ~250 bytes
#define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 1 // SAMSUNG AH >= 10000 ~250 bytes
#define IRMP_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes
#define IRMP_SUPPORT_GREE_PROTOCOL 1 // GREE CLIMATE >= 10000 <=17000 ~250 bytes
#define IRMP_SUPPORT_RCII_PROTOCOL 0 // RCII T+A >= 15000 ~250 bytes conflicts with GRUNDIG and NOKIA
#define IRMP_SUPPORT_METZ_PROTOCOL 1
#define IRMP_SUPPORT_MELINERA_PROTOCOL 1 // MELINERA (Lidl) >= 10000
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 2: RF decoders
* If you use an IR sensor, deactivate all RF protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes
#endif // _IRMP_SELECT_ALL_PROTOCOLS_H
================================================
FILE: src/irmpSelectAllRFProtocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpSelectAllRFProtocols.h
* 2 protocols enabled
*
* Copyright (c) 2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_SELECT_ALL_RF_PROTOCOLS_H
#define _IRMP_SELECT_ALL_RF_PROTOCOLS_H
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more decoders.
* This saves program memory.
*
* 1 enable decoder
* 0 disable decoder
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 2: RF decoders
* If you use an IR sensor, deactivate all RF protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_SUPPORT_RF_GEN24_PROTOCOL 1 // RF GEN24 (generic) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_X10_PROTOCOL 1 // RF PC X10 (Medion) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_MEDION_PROTOCOL 1 // RF PC Medion >= 15000 ~250 bytes
// Usually IR sensors are low active, RF receivers are high active.
#define IRMP_HIGH_ACTIVE 1 // set to 1 if you use a RF receiver!
#endif // _IRMP_SELECT_ALL_RF_PROTOCOLS_H
================================================
FILE: src/irmpSelectMain15Protocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpSelectMain15Protocols.h
*
*
* Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_SELECT_PROTOCOLS_H
#define _IRMP_SELECT_PROTOCOLS_H
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 (or deactivate it) if you want to disable one or more decoders.
* This saves program memory.
*
* 1 enable decoder
* 0 disable decoder
*
* The standard decoders are enabled per default.
* Less common protocols are disabled here, you need to enable them manually.
*
* If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required.
* If you don't need RC5 when using FDC/RCCAR, you should disable RC5.
* You cannot enable both DENON and RUWIDO, only enable one of them.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes
// more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL 1 // IR60 (SDA2008) >= 10000 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens Gigaset >= 15000 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~300 bytes
#endif // _IRMP_SELECT_PROTOCOLS_H
================================================
FILE: src/irmpVersion.h
================================================
/*
* irmpVersion.h
*
* Is used for IRMP and IRSND, and therefore a separate file
*
* Created on: 28.05.2020
* Author: Armin
*/
#ifndef _IRMPVERSION_H
#define _IRMPVERSION_H
#define VERSION_IRMP "3.7.0"
#define VERSION_IRMP_MAJOR 3
#define VERSION_IRMP_MINOR 7
#define VERSION_IRMP_PATCH 0
/*
* Macro to convert 3 version parts into an integer
* To be used in preprocessor comparisons, such as #if VERSION_IRMP_HEX >= VERSION_HEX_VALUE(3, 7, 0)
*/
#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#define VERSION_IRMP_HEX VERSION_HEX_VALUE(VERSION_IRMP_MAJOR, VERSION_IRMP_MINOR, VERSION_IRMP_PATCH)
#endif /* _IRMPVERSION_H */
================================================
FILE: src/irmpconfig.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpconfig.h
*
* DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H!
*
* Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de
* Extensions for PIC 12F1820 W.Strobl 2014-07-20
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_H_
# error please include only irmp.h, not irmpconfig.h
#endif
#if defined(IRMPCONFIG_STAGE1_H)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change IRMP_32_BIT here
*
* Normally, IRMP_32_BIT ist 0. Then we use irmp.command as a 16 bit value.
* If you set IRMP_32_BIT to 1, we will use irmp.command as a 32 bit value.
* A 32 bit command costs more CPU resources on 8 bit processors (e.g. AVR),
* but there are IR protocols which need more than 16 bits for a reasonable
* command value.
*
* If you want to use one of the following protocols, set IRMP_32_BIT to 1,
* otherwise set it to 0:
* - MERLIN
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_32_BIT)
# if __SIZEOF_INT__ == 4
# define IRMP_32_BIT 1 // use 32 bit command value, 0 or 1
# else
# define IRMP_32_BIT 0 // use 32 bit command value, 0 or 1
# endif
#endif
#endif // IRMPCONFIG_STAGE1_H
#if defined(IRMPCONFIG_STAGE2_H)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change F_INTERRUPTS if you change the number of interrupts per second,
* Normally, F_INTERRUPTS should be in the range from 10000 to 15000, typical is 15000
* A value above 15000 costs additional program memory, absolute maximum value is 20000.
* A value of 20000 is needed for Support of LEGO and RCMM, but it prevents using PENTAX or GREE
* since for 20000 they have 8 bit overflow issues because of the long start bits.
* On PIC with XC8/C18 Compiler, use 15151 as the correct value.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(F_INTERRUPTS)
# define F_INTERRUPTS 15000 // interrupts per second, 66,66us, min: 10000, max: 20000, typ: 15000
#endif
#if ! defined(ARDUINO)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more decoders.
* This saves program memory.
*
* 1 enable decoder
* 0 disable decoder
*
* The standard decoders are enabled per default.
* Less common protocols are disabled here, you need to enable them manually.
*
* If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required.
* If you don't need RC5 when using FDC/RCCAR, you should disable RC5.
* You cannot enable both DENON and RUWIDO, only enable one of them.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 1: IR decoders
* If you use a RF receiver, deactivate all IR protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes
#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes
// more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes
#define IRMP_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~100 bytes
#define IRMP_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~300 bytes
#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 0 // Matsushita >= 10000 ~50 bytes
#define IRMP_SUPPORT_DENON_PROTOCOL 0 // DENON, Sharp >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~250 bytes
#define IRMP_SUPPORT_RC6_PROTOCOL 0 // RC6 & RC6A >= 10000 ~250 bytes
#define IRMP_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~300 bytes
#define IRMP_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes
#define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens Gigaset >= 15000 ~550 bytes
#define IRMP_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~300 bytes
// exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRMP_SUPPORT_BOSE_PROTOCOL 0 // BOSE >= 10000 ~150 bytes
#define IRMP_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 ~200 bytes
#define IRMP_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~50 bytes
#define IRMP_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~50 bytes
#define IRMP_SUPPORT_SPEAKER_PROTOCOL 0 // SPEAKER (~NUBERT) >= 10000 ~50 bytes
#define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang & Olufsen >= 10000 ~200 bytes
#define IRMP_SUPPORT_RECS80_PROTOCOL 0 // RECS80 (SAA3004) >= 15000 ~50 bytes
#define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT (SAA3008) >= 15000 ~50 bytes
#define IRMP_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes
#define IRMP_SUPPORT_NIKON_PROTOCOL 0 // NIKON camera >= 10000 ~250 bytes
#define IRMP_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!)
#define IRMP_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 ~150 bytes
#define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 0 // Telefunken 1560 >= 10000 ~150 bytes
#define IRMP_SUPPORT_FDC_PROTOCOL 0 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5)
#define IRMP_SUPPORT_RCCAR_PROTOCOL 0 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5)
#define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes
#define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes
#define IRMP_SUPPORT_A1TVBOX_PROTOCOL 0 // A1 TV BOX >= 15000 (better 20000) ~300 bytes
#define IRMP_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes
#define IRMP_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 ~150 bytes
#define IRMP_SUPPORT_LGAIR_PROTOCOL 0 // LG Air Condition >= 10000 ~300 bytes
#define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 0 // Samsung48 >= 10000 ~100 bytes (SAMSUNG must be enabled!)
#define IRMP_SUPPORT_MERLIN_PROTOCOL 0 // Merlin >= 15000 (better 20000) ~300 bytes (requires IRMP_32_BIT=1)
#define IRMP_SUPPORT_PENTAX_PROTOCOL 0 // Pentax >= 10000 ~150 bytes
#define IRMP_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 ~250 bytes
#define IRMP_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~250 bytes
#define IRMP_SUPPORT_TECHNICS_PROTOCOL 0 // TECHNICS >= 10000 ~250 bytes
#define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~250 bytes
#define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi Aircond >= 10000 ~250 bytes
#define IRMP_SUPPORT_VINCENT_PROTOCOL 0 // VINCENT >= 10000 ~250 bytes
#define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 0 // SAMSUNG AH >= 10000 ~250 bytes
#define IRMP_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes
#define IRMP_SUPPORT_GREE_PROTOCOL 0 // GREE CLIMATE >= 10000 ~250 bytes
#define IRMP_SUPPORT_RCII_PROTOCOL 0 // RCII T+A >= 15000 ~250 bytes
#define IRMP_SUPPORT_METZ_PROTOCOL 0 // METZ >= 15000 ~250 bytes
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 2: RF decoders
* If you use an IR sensor, deactivate all RF protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes
#define IRMP_SUPPORT_MELINERA_PROTOCOL 0 // MELINERA (Lidl) >= 10000
#endif // ! defined(ARDUINO)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for ATMEL ATmega/ATTiny/XMega
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined (ATMEL_AVR) || defined (__AVR_XMEGA__) // use PB6 as IR input on AVR
# define IRMP_PORT_LETTER B
# define IRMP_BIT_NUMBER 6
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for PIC C18 or XC8 compiler
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (PIC_C18) // use RB4 as IR input on PIC (C18 or XC8 compiler)
# if defined(__12F1840)
# define IRMP_PIN RA5 // on 12F1840 with XC8 compiler
# else
# define IRMP_PIN PORTBbits.RB4 // PIC C18
# endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for PIC XC32 or ChipKIT compiler
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (PIC_XC32) // use RB13 as IR input on PIC (XC32 or ChipKIT compiler)
# define IRMP_PIN PORTBbits.RB13
# define IRMP_ANSELBIT ANSELBbits.ANSB13 // leave this undefined if the pin has no analog function
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for PIC CCS compiler
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (PIC_CCS)
# define IRMP_PIN PIN_B4 // use PB4 as IR input on PIC (CCS compiler)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for ARM STM32
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (ARM_STM32) // use C13 as IR input on STM32
# define IRMP_PORT_LETTER C
# define IRMP_BIT_NUMBER 13
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Hardware pin for ARM STM32 (HAL) - don't change here, define IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN in STM32Cube (Main.h)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (ARM_STM32_HAL) // STM32: IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN must be defined in STM32Cube
# define IRMP_PORT_LETTER IRMP_Receive_GPIO_Port
# define IRMP_BIT_NUMBER IRMP_Receive_Pin
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for Stellaris ARM Cortex M4
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (STELLARIS_ARM_CORTEX_M4) // use B4 as IR input on Stellaris LM4F
# define IRMP_PORT_LETTER B
# define IRMP_BIT_NUMBER 4
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for STM8
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (SDCC_STM8) // use PA1 as IR input on STM8
# define IRMP_PORT_LETTER A // change here
# define IRMP_BIT_NUMBER 1 // change here
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for ESP8266
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (__xtensa__)
# define IRMP_BIT_NUMBER 12 // use GPIO12 (Pin 7 UEXT) on ESP8266-EVB evaluation board
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for Teensy 3.x with teensyduino gcc compiler
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (TEENSY_ARM_CORTEX_M4)
# define IRMP_PIN 1 // use Digital pin 1 as IR input on Teensy
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for MBED
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(__MBED__)
# define IRMP_PIN P0_22 // use P1_27 on LPC1347
# define IRMP_PINMODE PullUp // hardware dependent
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change hardware pin here for ChibiOS HAL
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(_CHIBIOS_HAL_)
# define IRMP_PIN LINE_IR_IN // use pin names as defined in the board config file, prefixed with "LINE_"
# define IRMP_LOGGING_SD SD1 // the ChibiOS HAL Serial Driver instance to log to
// (when IRMP_LOGGING is enabled below).
// Make sure SERIAL_BUFFERS_SIZE is large enough when enabling logging
#elif defined(ARDUINO)
// specified here to avoid else case
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Handling of unknown target system: DON'T CHANGE
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif !defined (UNIX_OR_WINDOWS)
# error target system not defined.
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change if sensor is high active
*
* Usually IR sensors are low active, RF receivers are high active. Change here if you use a RF receiver!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_HIGH_ACTIVE)
# define IRMP_HIGH_ACTIVE 0 // set to 1 if you use a RF receiver!
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Enable detection of key releases
*
* If user releases a key on the remote control, last protocol/address/command will be returned with flag IRMP_FLAG_RELEASE set
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_ENABLE_RELEASE_DETECTION)
# define IRMP_ENABLE_RELEASE_DETECTION 0 // enable detection of key releases
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Set IRMP_LOGGING to 1 if want to log data to UART with 9600Bd
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_LOGGING)
# define IRMP_LOGGING 0 // 1: log IR signal (scan), 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Use external logging routines
* If you enable external logging, you have also to enable IRMP_LOGGING above
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_EXT_LOGGING)
# define IRMP_EXT_LOGGING 0 // 1: use external logging, 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Set IRMP_PROTOCOL_NAMES to 1 if want to access protocol names (for logging etc), costs ~300 bytes RAM!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_PROTOCOL_NAMES)
# define IRMP_PROTOCOL_NAMES 0 // 1: access protocol names, 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Use Callbacks to indicate input signal
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_USE_CALLBACK)
# define IRMP_USE_CALLBACK 0 // 1: use callbacks. 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Call the user-provided irmp_idle() function when IRMP is idle.
* Can be used to disable the timer irq and enter a sleep mode to save power
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_USE_IDLE_CALL)
# define IRMP_USE_IDLE_CALL 0 // 1: use idle calls. 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Use Callback if complete data was received
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRMP_USE_COMPLETE_CALLBACK)
# define IRMP_USE_COMPLETE_CALLBACK 0 // 1: use callback. 0: do not. default is 0
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Autodetect repeat rate
* For precise detection of key repetition (and key release)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef IRMP_AUTODETECT_REPEATRATE
# define IRMP_AUTODETECT_REPEATRATE 0 // 1: autodetect repeat rate. 0: do not. default is 0
# define JITTER_COMPENSATION 3 // percent, increase for remote controls with big jitter
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Use ChibiOS Events to signal that valid IR data was received
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_)
# if !defined(IRMP_USE_EVENT)
# define IRMP_USE_EVENT 0 // 1: use event. 0: do not. default is 0
# endif
# if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_BIT)
# define IRMP_EVENT_BIT 1 // event flag or bit to send
# endif
# if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_THREAD_PTR)
# define IRMP_EVENT_THREAD_PTR ir_receive_thread_p // pointer to the thread to send the event to
extern thread_t *IRMP_EVENT_THREAD_PTR; // the pointer must be defined and initialized elsewhere
# endif
#endif // _CHIBIOS_RT_ || _CHIBIOS_NIL_
#endif // _IRMPCONFIG_STAGE2_H_
================================================
FILE: src/irmpprotocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpprotocols.h - irmp protocols
*
* DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H or IRSND.H!
*
* Copyright (c) 2013-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMP_PROTOCOLS_H_
#define _IRMP_PROTOCOLS_H_
#if !defined(_IRMP_H_) && !defined(_IRSND_H_)
# error please include only irmp.h or irsnd.h, not irmpprotocols.h
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IR protocols:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_UNKNOWN_PROTOCOL 0 // unknown protocol
#define IRMP_SIRCS_PROTOCOL 1 // Sony
#define IRMP_NEC_PROTOCOL 2 // NEC with 32 bits, 16 address + 8 (+ 8 generated) command bits, Pioneer, JVC, Toshiba, NoName etc.
#define IRMP_SAMSUNG_PROTOCOL 3 // Samsung
#define IRMP_MATSUSHITA_PROTOCOL 4 // Matsushita
#define IRMP_KASEIKYO_PROTOCOL 5 // Kaseikyo (Panasonic etc)
#define IRMP_RECS80_PROTOCOL 6 // Philips, Thomson, Nordmende, Telefunken, Saba
#define IRMP_RC5_PROTOCOL 7 // Philips etc
#define IRMP_DENON_PROTOCOL 8 // Denon, Sharp
#define IRMP_RC6_PROTOCOL 9 // Philips etc
#define IRMP_SAMSUNG32_PROTOCOL 10 // Samsung32: no sync pulse at bit 16, length 32 instead of 37
#define IRMP_APPLE_PROTOCOL 11 // Apple, very similar to NEC
#define IRMP_RECS80EXT_PROTOCOL 12 // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba
#define IRMP_NUBERT_PROTOCOL 13 // Nubert
#define IRMP_BANG_OLUFSEN_PROTOCOL 14 // Bang & Olufsen
#define IRMP_GRUNDIG_PROTOCOL 15 // Grundig
#define IRMP_NOKIA_PROTOCOL 16 // Nokia
#define IRMP_SIEMENS_PROTOCOL 17 // Siemens, e.g. Gigaset
#define IRMP_FDC_PROTOCOL 18 // FDC keyboard
#define IRMP_RCCAR_PROTOCOL 19 // RC Car
#define IRMP_JVC_PROTOCOL 20 // JVC (NEC with 16 bits)
#define IRMP_RC6A_PROTOCOL 21 // RC6A, e.g. Kathrein, XBOX
#define IRMP_NIKON_PROTOCOL 22 // Nikon
#define IRMP_RUWIDO_PROTOCOL 23 // Ruwido, e.g. T-Home Mediareceiver
#define IRMP_IR60_PROTOCOL 24 // IR60 (SDA2008)
#define IRMP_KATHREIN_PROTOCOL 25 // Kathrein
#define IRMP_NETBOX_PROTOCOL 26 // Netbox keyboard (bitserial)
#define IRMP_NEC16_PROTOCOL 27 // NEC with 16 bits (incl. sync)
#define IRMP_NEC42_PROTOCOL 28 // NEC with 42 bits
#define IRMP_LEGO_PROTOCOL 29 // LEGO Power Functions RC
#define IRMP_THOMSON_PROTOCOL 30 // Thomson
#define IRMP_BOSE_PROTOCOL 31 // BOSE
#define IRMP_A1TVBOX_PROTOCOL 32 // A1 TV Box
#define IRMP_ORTEK_PROTOCOL 33 // ORTEK - Hama
#define IRMP_TELEFUNKEN_PROTOCOL 34 // Telefunken (1560)
#define IRMP_ROOMBA_PROTOCOL 35 // iRobot Roomba vacuum cleaner
#define IRMP_RCMM32_PROTOCOL 36 // Fujitsu-Siemens (Activy remote control)
#define IRMP_RCMM24_PROTOCOL 37 // Fujitsu-Siemens (Activy keyboard)
#define IRMP_RCMM12_PROTOCOL 38 // Fujitsu-Siemens (Activy keyboard)
#define IRMP_SPEAKER_PROTOCOL 39 // Another loudspeaker protocol, similar to Nubert
#define IRMP_LGAIR_PROTOCOL 40 // LG air conditioner
#define IRMP_SAMSUNG48_PROTOCOL 41 // air conditioner with SAMSUNG protocol (48 bits)
#define IRMP_MERLIN_PROTOCOL 42 // Merlin (Pollin 620 185)
#define IRMP_PENTAX_PROTOCOL 43 // Pentax camera
#define IRMP_FAN_PROTOCOL 44 // FAN (ventilator), very similar to NUBERT, but last bit is data bit instead of stop bit
#define IRMP_S100_PROTOCOL 45 // very similar to RC5, but 14 instead of 13 data bits
#define IRMP_ACP24_PROTOCOL 46 // Stiebel Eltron ACP24 air conditioner
#define IRMP_TECHNICS_PROTOCOL 47 // Technics, similar to Matsushita, but 22 instead of 24 bits
#define IRMP_PANASONIC_PROTOCOL 48 // Panasonic (Beamer), start bits similar to KASEIKYO
#define IRMP_MITSU_HEAVY_PROTOCOL 49 // Mitsubishi-Heavy Aircondition, similar timing as Panasonic beamer
#define IRMP_VINCENT_PROTOCOL 50 // Vincent
#define IRMP_SAMSUNGAH_PROTOCOL 51 // SAMSUNG AH
#define IRMP_IRMP16_PROTOCOL 52 // IRMP specific protocol for data transfer, e.g. between two microcontrollers via IR
#define IRMP_GREE_PROTOCOL 53 // Gree climate
#define IRMP_RCII_PROTOCOL 54 // RC II Infra Red Remote Control Protocol for FM8
#define IRMP_METZ_PROTOCOL 55 // METZ
#define IRMP_ONKYO_PROTOCOL 56 // Like NEC but with 16 address + 16 command bits
#define RF_GEN24_PROTOCOL 57 // RF Generic, 24 Bits (Pollin 550666, EAN 4049702006022 and many other similar RF remote controls))
#define RF_X10_PROTOCOL 58 // RF PC X10 Remote Control (Medion, Pollin 721815)
#define RF_MEDION_PROTOCOL 59 // RF PC Medion Remote Control (Medion)
#define IRMP_MELINERA_PROTOCOL 60
#define IRMP_RC6A20_PROTOCOL 61 // RC6A20, e.g. Sky+
#define IRMP_RC6A28_PROTOCOL 62 // RC6A28, e.g. Sky Q (Sky+ Pro)
#define IRMP_N_PROTOCOLS 62 // number of supported protocols
#if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1 || IRSND_PROTOCOL_NAMES == 1
extern const char proto_unknown[] PROGMEM;
extern const char proto_sircs[] PROGMEM;
extern const char proto_nec[] PROGMEM;
extern const char proto_samsung[] PROGMEM;
extern const char proto_matsushita[] PROGMEM;
extern const char proto_kaseikyo[] PROGMEM;
extern const char proto_recs80[] PROGMEM;
extern const char proto_rc5[] PROGMEM;
extern const char proto_denon[] PROGMEM;
extern const char proto_rc6[] PROGMEM;
extern const char proto_samsung32[] PROGMEM;
extern const char proto_apple[] PROGMEM;
extern const char proto_recs80ext[] PROGMEM;
extern const char proto_nubert[] PROGMEM;
extern const char proto_bang_olufsen[] PROGMEM;
extern const char proto_grundig[] PROGMEM;
extern const char proto_nokia[] PROGMEM;
extern const char proto_siemens[] PROGMEM;
extern const char proto_fdc[] PROGMEM;
extern const char proto_rccar[] PROGMEM;
extern const char proto_jvc[] PROGMEM;
extern const char proto_rc6a[] PROGMEM;
extern const char proto_nikon[] PROGMEM;
extern const char proto_ruwido[] PROGMEM;
extern const char proto_ir60[] PROGMEM;
extern const char proto_kathrein[] PROGMEM;
extern const char proto_netbox[] PROGMEM;
extern const char proto_nec16[] PROGMEM;
extern const char proto_nec42[] PROGMEM;
extern const char proto_lego[] PROGMEM;
extern const char proto_thomson[] PROGMEM;
extern const char proto_bose[] PROGMEM;
extern const char proto_a1tvbox[] PROGMEM;
extern const char proto_ortek[] PROGMEM;
extern const char proto_telefunken[] PROGMEM;
extern const char proto_roomba[] PROGMEM;
extern const char proto_rcmm32[] PROGMEM;
extern const char proto_rcmm24[] PROGMEM;
extern const char proto_rcmm12[] PROGMEM;
extern const char proto_speaker[] PROGMEM;
extern const char proto_lgair[] PROGMEM;
extern const char proto_samsung48[] PROGMEM;
extern const char proto_merlin[] PROGMEM;
extern const char proto_pentax[] PROGMEM;
extern const char proto_fan[] PROGMEM;
extern const char proto_s100[] PROGMEM;
extern const char proto_acp24[] PROGMEM;
extern const char proto_technics[] PROGMEM;
extern const char proto_panasonic[] PROGMEM;
extern const char proto_mitsu_heavy[] PROGMEM;
extern const char proto_vincent[] PROGMEM;
extern const char proto_samsungah[] PROGMEM;
extern const char proto_irmp16[] PROGMEM;
extern const char proto_gree[] PROGMEM;
extern const char proto_rcii[] PROGMEM;
extern const char proto_metz[] PROGMEM;
extern const char proto_onkyo[] PROGMEM;
extern const char proto_rf_gen24[] PROGMEM;
extern const char proto_rf_x10[] PROGMEM;
extern const char proto_rf_medion[] PROGMEM;
extern const char proto_melinera[] PROGMEM;
extern const char proto_rc6a20[] PROGMEM;
extern const char proto_rc6a28[] PROGMEM;
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* timing constants:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// fm 22.09.2011: may not be more than 16000L, otherwise some JVC codes will not be accepted
#define IRMP_TIMEOUT_TIME 15500.0e-6 // timeout after 15.5 ms darkness
#define IRMP_TIMEOUT_TIME_MS 15500L // timeout after 15.5 ms darkness
#if IRMP_SUPPORT_NIKON_PROTOCOL == 1
# define IRMP_TIMEOUT_NIKON_TIME 29500.0e-6 // 2nd timeout after 29.5 ms darkness (only for NIKON!)
# define IRMP_TIMEOUT_NIKON_TIME_MS 29500L // 2nd timeout after 29.5 ms darkness
typedef uint16_t PAUSE_LEN;
# define IRMP_TIMEOUT_NIKON_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_NIKON_TIME + 0.5)
#else
# if (F_INTERRUPTS * IRMP_TIMEOUT_TIME_MS) / 1000000 >= 254
typedef uint16_t PAUSE_LEN;
# else
typedef uint8_t PAUSE_LEN;
# endif
#endif
#define IRMP_TIMEOUT_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_TIME + 0.5)
#define IRMP_KEY_RELEASE_TIME 25.0e-3 // key release timeout detection after 25.0 ms darkness
#define IRMP_KEY_RELEASE_LEN (uint16_t)(F_INTERRUPTS * IRMP_KEY_RELEASE_TIME + 0.5)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* flags of struct IRMP_PARAMETER:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_PARAM_FLAG_IS_MANCHESTER 0x01
#define IRMP_PARAM_FLAG_1ST_PULSE_IS_1 0x02
#define IRMP_PARAM_FLAG_IS_SERIAL 0x04
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* SIRCS:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define SIRCS_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse
#define SIRCS_START_BIT_PAUSE_TIME 600.0e-6 // 600 usec pause
#define SIRCS_1_PULSE_TIME 1200.0e-6 // 1200 usec pulse
#define SIRCS_0_PULSE_TIME 600.0e-6 // 600 usec pulse
#define SIRCS_PAUSE_TIME 600.0e-6 // 600 usec pause
#define SIRCS_FRAMES 3 // SIRCS sends each frame 3 times
#define SIRCS_AUTO_REPETITION_PAUSE_TIME 25.0e-3 // auto repetition after 25ms
#define SIRCS_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms
#define SIRCS_ADDRESS_OFFSET 15 // skip 15 bits
#define SIRCS_ADDRESS_LEN 5 // read up to 5 address bits
#define SIRCS_COMMAND_OFFSET 0 // skip 0 bits
#define SIRCS_COMMAND_LEN 15 // read 12-15 command bits
#define SIRCS_MINIMUM_DATA_LEN 12 // minimum data length
#define SIRCS_COMPLETE_DATA_LEN 20 // complete length - may be up to 20
#define SIRCS_STOP_BIT 0 // has no stop bit
#define SIRCS_LSB 1 // LSB...MSB
#define SIRCS_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* NEC & NEC42 & NEC16 & LGAIR & MELINERA:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define NEC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse
#define NEC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause
#define NEC_REPEAT_START_BIT_PAUSE_TIME 2250.0e-6 // 2250 usec pause
#define NEC_PULSE_TIME 560.0e-6 // 560 usec pulse
#define NEC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause
#define NEC_0_PAUSE_TIME 560.0e-6 // 560 usec pause
#define NEC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define NEC_ADDRESS_OFFSET 0 // skip 0 bits
#define NEC_ADDRESS_LEN 16 // read 16 address bits
#define NEC_COMMAND_OFFSET 16 // skip 16 bits (8 address + 8 /address)
#define NEC_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command)
#define NEC_COMPLETE_DATA_LEN 32 // complete length
#define NEC_STOP_BIT 1 // has stop bit
#define NEC_LSB 1 // LSB...MSB
#define NEC_FLAGS 0 // flags
#define NEC42_ADDRESS_OFFSET 0 // skip 0 bits
#define NEC42_ADDRESS_LEN 13 // read 13 address bits
#define NEC42_COMMAND_OFFSET 26 // skip 26 bits (2 x 13 address bits)
#define NEC42_COMMAND_LEN 8 // read 8 command bits
#define NEC42_COMPLETE_DATA_LEN 42 // complete length (2 x 13 + 2 x 8)
#define LGAIR_ADDRESS_OFFSET 0 // skip 0 bits
#define LGAIR_ADDRESS_LEN 8 // read 8 address bits
#define LGAIR_COMMAND_OFFSET 8 // skip 8 bits (8 address)
#define LGAIR_COMMAND_LEN 16 // read 16 bits (16 command)
#define LGAIR_COMPLETE_DATA_LEN 28 // complete length (8 address + 16 command + 4 checksum)
#define NEC16_ADDRESS_OFFSET 0 // skip 0 bits
#define NEC16_ADDRESS_LEN 8 // read 8 address bits
#define NEC16_COMMAND_OFFSET 8 // skip 8 bits (8 address)
#define NEC16_COMMAND_LEN 8 // read 8 bits (8 command)
#define NEC16_COMPLETE_DATA_LEN 16 // complete length
#define MELINERA_START_BIT_PULSE_TIME 8800.0e-6 // 8800 usec pulse
#define MELINERA_START_BIT_PAUSE_TIME 4100.0e-6 // 4100 usec pause
#define MELINERA_0_PULSE_TIME 440.0e-6 // 430 usec pause
#define MELINERA_0_PAUSE_TIME 590.0e-6 // 600 usec pause
#define MELINERA_1_PULSE_TIME 970.0e-6 // 910 usec pause
#define MELINERA_1_PAUSE_TIME 1140.0e-6 // 1160 usec pause
#define MELINERA_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define MELINERA_ADDRESS_OFFSET 0 // skip 0 bits
#define MELINERA_ADDRESS_LEN 0 // read 0 address bits
#define MELINERA_COMMAND_OFFSET 0 // skip 0 bits (0 address)
#define MELINERA_COMMAND_LEN 8 // read 8 bits (8 command)
#define MELINERA_COMPLETE_DATA_LEN 8 // complete length
#define MELINERA_STOP_BIT 1 // has stop bit
#define MELINERA_LSB 0 // MSB
#define MELINERA_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* SAMSUNG & SAMSUNG32 & SAMSUNG48:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define SAMSUNG_START_BIT_PULSE_TIME 4500.0e-6 // 4500 usec pulse
#define SAMSUNG_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause
#define SAMSUNG_PULSE_TIME 550.0e-6 // 550 usec pulse
#define SAMSUNG_1_PAUSE_TIME 1500.0e-6 // 1550 usec pause
#define SAMSUNG_0_PAUSE_TIME 500.0e-6 // 500 usec pause
#define SAMSUNG_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms
#define SAMSUNG_ADDRESS_OFFSET 0 // skip 0 bits
#define SAMSUNG_ADDRESS_LEN 16 // read 16 address bits
#define SAMSUNG_ID_OFFSET 17 // skip 16 + 1 sync bit
#define SAMSUNG_ID_LEN 4 // read 4 id bits
#define SAMSUNG_COMMAND_OFFSET 21 // skip 16 + 1 sync + 4 data bits
#define SAMSUNG_COMMAND_LEN 16 // read 16 command bits
#define SAMSUNG_COMPLETE_DATA_LEN 37 // complete length
#define SAMSUNG_STOP_BIT 1 // has stop bit
#define SAMSUNG_LSB 1 // LSB...MSB?
#define SAMSUNG_FLAGS 0 // flags
#define SAMSUNG32_COMMAND_OFFSET 16 // skip 16 bits
#define SAMSUNG32_COMMAND_LEN 16 // read 16 command bits
#define SAMSUNG32_COMPLETE_DATA_LEN 32 // complete length
#define SAMSUNG32_FRAMES 1 // SAMSUNG32 sends one frame
#define SAMSUNG32_AUTO_REPETITION_PAUSE_TIME 47.0e-3 // repetition after 47 ms
#define SAMSUNG32_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms
#define SAMSUNG48_COMMAND_OFFSET 16 // skip 16 bits
#define SAMSUNG48_COMMAND_LEN 32 // read 32 command bits
#define SAMSUNG48_COMPLETE_DATA_LEN 48 // complete length
#define SAMSUNG48_FRAMES 2 // SAMSUNG48 sends each frame 2 times
#define SAMSUNG48_AUTO_REPETITION_PAUSE_TIME 5.0e-3 // repetition after 5 ms
#define SAMSUNG48_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* SAMSUNGAH:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define SAMSUNGAH_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse
#define SAMSUNGAH_START_BIT_PAUSE_TIME 1900.0e-6 // 1900 usec pause
#define SAMSUNGAH_PULSE_TIME 450.0e-6 // 450 usec pulse
#define SAMSUNGAH_1_PAUSE_TIME 1100.0e-6 // 1100 usec pause
#define SAMSUNGAH_0_PAUSE_TIME 450.0e-6 // 450 usec pause
#define SAMSUNGAH_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define SAMSUNGAH_ADDRESS_OFFSET 0 // skip 0 bits
#define SAMSUNGAH_ADDRESS_LEN 16 // read 16 address bits, ignore 17..31
#define SAMSUNGAH_COMMAND_OFFSET 32 // skip 32 bits
#define SAMSUNGAH_COMMAND_LEN 16 // read 32 bits
#define SAMSUNGAH_COMPLETE_DATA_LEN 48 // complete length
#define SAMSUNGAH_STOP_BIT 1 // has stop bit
#define SAMSUNGAH_LSB 1 // LSB...MSB?
#define SAMSUNGAH_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* MATSUSHITA:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define MATSUSHITA_START_BIT_PULSE_TIME 3488.0e-6 // 3488 usec pulse
#define MATSUSHITA_START_BIT_PAUSE_TIME 3488.0e-6 // 3488 usec pause
#define MATSUSHITA_PULSE_TIME 872.0e-6 // 872 usec pulse
#define MATSUSHITA_1_PAUSE_TIME 2616.0e-6 // 2616 usec pause
#define MATSUSHITA_0_PAUSE_TIME 872.0e-6 // 872 usec pause
#define MATSUSHITA_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define MATSUSHITA_ADDRESS_OFFSET 12 // skip 12 bits
#define MATSUSHITA_ADDRESS_LEN 12 // read 12 address bits
#define MATSUSHITA_COMMAND_OFFSET 0 // skip 0 bits
#define MATSUSHITA_COMMAND_LEN 12 // read 12 bits (6 custom + 6 command)
#define MATSUSHITA_COMPLETE_DATA_LEN 24 // complete length
#define MATSUSHITA_STOP_BIT 1 // has stop bit
#define MATSUSHITA_LSB 1 // LSB...MSB?
#define MATSUSHITA_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* TECHNICS: same timings as MATSUSHITA
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define TECHNICS_ADDRESS_LEN 0 // read 0 address bits
#define TECHNICS_COMMAND_LEN 11 // read 11 bits
#define TECHNICS_COMPLETE_DATA_LEN 22 // complete length
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* KASEIKYO: 48 bit
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define KASEIKYO_START_BIT_PULSE_TIME 3456.0e-6 // 3380 usec pulse
#define KASEIKYO_START_BIT_PAUSE_TIME 1728.0e-6 // 1690 usec pause
#define KASEIKYO_PULSE_TIME 432.0e-6 // 525 usec pulse
#define KASEIKYO_1_PAUSE_TIME 1296.0e-6 // 525 usec pause
#define KASEIKYO_0_PAUSE_TIME 432.0e-6 // 1690 usec pause
#define KASEIKYO_AUTO_REPETITION_PAUSE_TIME 74.0e-3 // repetition after 74 ms
#define KASEIKYO_FRAME_REPEAT_PAUSE_TIME 74.0e-3 // frame repeat after 74 ms
#define KASEIKYO_ADDRESS_OFFSET 0 // skip 0 bits
#define KASEIKYO_ADDRESS_LEN 16 // read 16 address / manufacturer bits
#define KASEIKYO_COMMAND_OFFSET 28 // skip 28 bits (16 manufacturer & 4 parity & 8 genre)
#define KASEIKYO_COMMAND_LEN 12 // read 12 command bits (10 real command & 2 id)
#define KASEIKYO_COMPLETE_DATA_LEN 48 // complete length
#define KASEIKYO_STOP_BIT 1 // has stop bit
#define KASEIKYO_LSB 1 // LSB...MSB?
#define KASEIKYO_FRAMES 1 // KASEIKYO sends 1 frame
#define KASEIKYO_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* PANASONIC (Beamer), start bit timings similar to KASEIKYO 56 bit
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define PANASONIC_START_BIT_PULSE_TIME 3600.0e-6 // 3600 usec pulse
#define PANASONIC_START_BIT_PAUSE_TIME 1600.0e-6 // 1690 usec pause
#define PANASONIC_PULSE_TIME 432.0e-6 // 565 usec pulse
#define PANASONIC_1_PAUSE_TIME 1296.0e-6 // 1140 usec pause
#define PANASONIC_0_PAUSE_TIME 432.0e-6 // 316 usec pause
#define PANASONIC_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40 ms?
#define PANASONIC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms
#define PANASONIC_ADDRESS_OFFSET 24 // skip 24 bits: 010000000000010000000001
#define PANASONIC_ADDRESS_LEN 16 // read 16 address bits
#define PANASONIC_COMMAND_OFFSET 40 // skip 40 bits
#define PANASONIC_COMMAND_LEN 16 // read 16 command bits
#define PANASONIC_COMPLETE_DATA_LEN 56 // complete length
#define PANASONIC_STOP_BIT 1 // has stop bit
#define PANASONIC_LSB 1 // LSB...MSB?
#define PANASONIC_FRAMES 1 // PANASONIC sends 1 frame
#define PANASONIC_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* MITSUBISHI-Heavy Aircondition, timings similar to PANASONIC beamer 88 bit
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define MITSU_HEAVY_START_BIT_PULSE_TIME 3200.0e-6 // 3600 usec pulse
#define MITSU_HEAVY_START_BIT_PAUSE_TIME 1560.0e-6 // 1690 usec pause
#define MITSU_HEAVY_PULSE_TIME 400.0e-6 // 565 usec pulse
#define MITSU_HEAVY_1_PAUSE_TIME 1200.0e-6 // 1140 usec pause
#define MITSU_HEAVY_0_PAUSE_TIME 430.0e-6 // 316 usec pause
#define MITSU_HEAVY_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms
#define MITSU_HEAVY_ADDRESS_OFFSET 40 // skip 24 bits: 010000000000010000000001
#define MITSU_HEAVY_ADDRESS_LEN 16 // read 16 address bits
#define MITSU_HEAVY_COMMAND_OFFSET 56 // skip 40 bits
#define MITSU_HEAVY_COMMAND_LEN 16 // read 16 command bits
#define MITSU_HEAVY_COMPLETE_DATA_LEN 88 // complete length
#define MITSU_HEAVY_STOP_BIT 1 // has stop bit
#define MITSU_HEAVY_LSB 0 // LSB...MSB?
#define MITSU_HEAVY_FRAMES 1 // PANASONIC sends 1 frame
#define MITSU_HEAVY_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* VINCENT
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define VINCENT_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse
#define VINCENT_START_BIT_PAUSE_TIME 4600.0e-6 // 4600 usec pause
#define VINCENT_PULSE_TIME 550.0e-6 // 550 usec pulse
#define VINCENT_1_PAUSE_TIME 1540.0e-6 // 1540 usec pause
#define VINCENT_0_PAUSE_TIME 550.0e-6 // 550 usec pause
#define VINCENT_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms ?
#define VINCENT_ADDRESS_OFFSET 0 // skip 0 bits
#define VINCENT_ADDRESS_LEN 16 // read 16 address bits
#define VINCENT_COMMAND_OFFSET 16 // skip 16 bits
#define VINCENT_COMMAND_LEN 16 // read 16 command bits
#define VINCENT_COMPLETE_DATA_LEN 32 // complete length
#define VINCENT_STOP_BIT 1 // has stop bit
#define VINCENT_LSB 0 // LSB...MSB?
#define VINCENT_FRAMES 1 // VINCENT sends 1 frame
#define VINCENT_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RECS80:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RECS80_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse
#define RECS80_START_BIT_PAUSE_TIME 7432.0e-6 // 7432 usec pause
#define RECS80_PULSE_TIME 158.0e-6 // 158 usec pulse
#define RECS80_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause
#define RECS80_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause
#define RECS80_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define RECS80_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit)
#define RECS80_ADDRESS_LEN 3 // read 3 address bits
#define RECS80_COMMAND_OFFSET 4 // skip 4 bits (1 toggle + 3 address)
#define RECS80_COMMAND_LEN 6 // read 6 command bits
#define RECS80_COMPLETE_DATA_LEN 10 // complete length
#define RECS80_STOP_BIT 1 // has stop bit
#define RECS80_LSB 0 // MSB...LSB
#define RECS80_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RC5:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RC5_BIT_TIME 889.0e-6 // 889 usec pulse/pause
#define RC5_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms
#define RC5_ADDRESS_OFFSET 1 // skip 1 bit (2nd start)
#define RC5_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits
#define RC5_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address)
#define RC5_COMMAND_LEN 6 // read 6 command bits
#define RC5_COMPLETE_DATA_LEN 13 // complete length
#define RC5_STOP_BIT 0 // has no stop bit
#define RC5_LSB 0 // MSB...LSB
#define RC5_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RCII:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RCII_START_BIT_PULSE_TIME 512.0e-6 // 512 usec pulse
#define RCII_START_BIT_PAUSE_TIME 2560.0e-6 // 2560 usec pause
#define RCII_START_BIT2_PULSE_TIME 1024.0e-6 // 1024 usec pulse
#define RCII_BIT_TIME 512.0e-6 // 512 usec pulse/pause
#define RCII_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // frame repeat after 117.76ms
#define RCII_ADDRESS_OFFSET 0 // skip 1 bit (2nd start)
#define RCII_ADDRESS_LEN 0 // no address
#define RCII_COMMAND_OFFSET 0 // command offset is 0
#define RCII_COMMAND_LEN 10 // read 1 + 9 command bits
#define RCII_COMPLETE_DATA_LEN 10 // complete length
#define RCII_STOP_BIT 0 // has no stop bit
#define RCII_LSB 0 // MSB...LSB
#define RCII_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* S100: very similar to RC5, but 14 insted of 13 bits
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define S100_BIT_TIME 889.0e-6 // 889 usec pulse/pause
#define S100_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms
#define S100_ADDRESS_OFFSET 1 // skip 1 bit (2nd start)
#define S100_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits
#define S100_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address)
#define S100_COMMAND_LEN 7 // read 7 command bits
#define S100_COMPLETE_DATA_LEN 14 // complete length
#define S100_STOP_BIT 0 // has no stop bit
#define S100_LSB 0 // MSB...LSB
#define S100_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* DENON:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define DENON_PULSE_TIME 310.0e-6 // 310 usec pulse in practice, 275 in theory
#define DENON_1_PAUSE_TIME 1780.0e-6 // 1780 usec pause in practice, 1900 in theory
#define DENON_0_PAUSE_TIME 745.0e-6 // 745 usec pause in practice, 775 in theory
#define DENON_FRAMES 2 // DENON sends each frame 2 times
#define DENON_AUTO_REPETITION_PAUSE_TIME 45.0e-3 // inverted repetition after 45ms
#define DENON_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define DENON_ADDRESS_OFFSET 0 // skip 0 bits
#define DENON_ADDRESS_LEN 5 // read 5 address bits
#define DENON_COMMAND_OFFSET 5 // skip 5
#define DENON_COMMAND_LEN 10 // read 10 command bits
#define DENON_COMPLETE_DATA_LEN 15 // complete length
#define DENON_STOP_BIT 1 // has stop bit
#define DENON_LSB 0 // MSB...LSB
#define DENON_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RC6:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RC6_START_BIT_PULSE_TIME 2666.0e-6 // 2.666 msec pulse
#define RC6_START_BIT_PAUSE_TIME 889.0e-6 // 889 usec pause
#define RC6_TOGGLE_BIT_TIME 889.0e-6 // 889 msec pulse/pause
#define RC6_BIT_TIME 444.0e-6 // 444 usec pulse/pause
#define RC6_BIT_2_TIME 889.0e-6 // 889 usec pulse/pause
#define RC6_BIT_3_TIME 1333.0e-6 // 1333 usec pulse/pause
#define RC6_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define RC6_ADDRESS_OFFSET 5 // skip "1" + 3 mode bits + 1 toggle bit
#define RC6_ADDRESS_LEN 8 // read 8 address bits
#define RC6_COMMAND_OFFSET 13 // skip 12 bits ("1" + 3 mode + 1 toggle + 8 address)
#define RC6_COMMAND_LEN 8 // read 8 command bits
#define RC6_COMPLETE_DATA_LEN_SHORT 21 // complete length
#define RC6_COMPLETE_DATA_LEN_20 25 // complete length
#define RC6_COMPLETE_DATA_LEN_28 33 // complete length
#define RC6_COMPLETE_DATA_LEN_LONG 36 // complete length
#define RC6_STOP_BIT 0 // has no stop bit
#define RC6_LSB 0 // MSB...LSB
#define RC6_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RECS80EXT:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RECS80EXT_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse
#define RECS80EXT_START_BIT_PAUSE_TIME 3637.0e-6 // 3637 usec pause
#define RECS80EXT_PULSE_TIME 158.0e-6 // 158 usec pulse
#define RECS80EXT_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause
#define RECS80EXT_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause
#define RECS80EXT_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define RECS80EXT_ADDRESS_OFFSET 2 // skip 2 bits (2nd start + 1 toggle)
#define RECS80EXT_ADDRESS_LEN 4 // read 4 address bits
#define RECS80EXT_COMMAND_OFFSET 6 // skip 6 bits (2nd start + 1 toggle + 4 address)
#define RECS80EXT_COMMAND_LEN 6 // read 6 command bits
#define RECS80EXT_COMPLETE_DATA_LEN 12 // complete length
#define RECS80EXT_STOP_BIT 1 // has stop bit
#define RECS80EXT_LSB 0 // MSB...LSB
#define RECS80EXT_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* NUBERT:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define NUBERT_START_BIT_PULSE_TIME 1340.0e-6 // 1340 usec pulse
#define NUBERT_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause
#define NUBERT_1_PULSE_TIME 1340.0e-6 // 1340 usec pulse
#define NUBERT_1_PAUSE_TIME 340.0e-6 // 340 usec pause
#define NUBERT_0_PULSE_TIME 500.0e-6 // 500 usec pulse
#define NUBERT_0_PAUSE_TIME 1300.0e-6 // 1300 usec pause
#define NUBERT_FRAMES 2 // Nubert sends 2 frames
#define NUBERT_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms
#define NUBERT_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms
#define NUBERT_ADDRESS_OFFSET 0 // skip 0 bits
#define NUBERT_ADDRESS_LEN 0 // read 0 address bits
#define NUBERT_COMMAND_OFFSET 0 // skip 0 bits
#define NUBERT_COMMAND_LEN 10 // read 10 bits
#define NUBERT_COMPLETE_DATA_LEN 10 // complete length
#define NUBERT_STOP_BIT 1 // has stop bit
#define NUBERT_LSB 0 // MSB?
#define NUBERT_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* FAN: (ventilator)
*
* Similar to NUBERT, but
* - has data bit instead of stop bit
* - has NO frame repetition
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define FAN_START_BIT_PULSE_TIME 1280.0e-6 // 1280 usec pulse
#define FAN_START_BIT_PAUSE_TIME 380.0e-6 // 380 usec pause
#define FAN_1_PULSE_TIME 1280.0e-6 // 1280 usec pulse
#define FAN_1_PAUSE_TIME 380.0e-6 // 380 usec pause
#define FAN_0_PULSE_TIME 380.0e-6 // 380 usec pulse
#define FAN_0_PAUSE_TIME 1280.0e-6 // 1280 usec pause
#define FAN_FRAMES 1 // FAN sends only 1 frame (NUBERT sends 2)
#define FAN_AUTO_REPETITION_PAUSE_TIME 6.6e-3 // auto repetition after 6.6ms
#define FAN_FRAME_REPEAT_PAUSE_TIME 6.6e-3 // frame repeat after 6.6ms
#define FAN_ADDRESS_OFFSET 0 // skip 0 bits
#define FAN_ADDRESS_LEN 0 // read 0 address bits
#define FAN_COMMAND_OFFSET 0 // skip 0 bits
#define FAN_COMMAND_LEN 11 // read 10 bits
#define FAN_COMPLETE_DATA_LEN 11 // complete length
#define FAN_STOP_BIT 0 // has NO stop bit (fm: this seems to be wrong)
#define FAN_LSB 0 // MSB
#define FAN_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* SPEAKER:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define SPEAKER_START_BIT_PULSE_TIME 440.0e-6 // 440 usec pulse
#define SPEAKER_START_BIT_PAUSE_TIME 1250.0e-6 // 1250 usec pause
#define SPEAKER_1_PULSE_TIME 1250.0e-6 // 1250 usec pulse
#define SPEAKER_1_PAUSE_TIME 440.0e-6 // 440 usec pause
#define SPEAKER_0_PULSE_TIME 440.0e-6 // 440 usec pulse
#define SPEAKER_0_PAUSE_TIME 1250.0e-6 // 1250 usec pause
#define SPEAKER_FRAMES 2 // SPEAKER sends 2 frames
#define SPEAKER_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms
#define SPEAKER_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms
#define SPEAKER_ADDRESS_OFFSET 0 // skip 0 bits
#define SPEAKER_ADDRESS_LEN 0 // read 0 address bits
#define SPEAKER_COMMAND_OFFSET 0 // skip 0 bits
#define SPEAKER_COMMAND_LEN 10 // read 10 bits
#define SPEAKER_COMPLETE_DATA_LEN 10 // complete length
#define SPEAKER_STOP_BIT 1 // has stop bit
#define SPEAKER_LSB 0 // MSB?
#define SPEAKER_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* BANG_OLUFSEN:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define BANG_OLUFSEN_START_BIT1_PULSE_TIME 200.0e-6 // 200 usec pulse
#define BANG_OLUFSEN_START_BIT1_PAUSE_TIME 3125.0e-6 // 3125 usec pause
#define BANG_OLUFSEN_START_BIT2_PULSE_TIME 200.0e-6 // 200 usec pulse
#define BANG_OLUFSEN_START_BIT2_PAUSE_TIME 3125.0e-6 // 3125 usec pause
#define BANG_OLUFSEN_START_BIT3_PULSE_TIME 200.0e-6 // 200 usec pulse
#define BANG_OLUFSEN_START_BIT3_PAUSE_TIME 15625.0e-6 // 15625 usec pause
#define BANG_OLUFSEN_START_BIT4_PULSE_TIME 200.0e-6 // 200 usec pulse
#define BANG_OLUFSEN_START_BIT4_PAUSE_TIME 3125.0e-6 // 3125 usec pause
#define BANG_OLUFSEN_PULSE_TIME 200.0e-6 // 200 usec pulse
#define BANG_OLUFSEN_1_PAUSE_TIME 9375.0e-6 // 9375 usec pause
#define BANG_OLUFSEN_0_PAUSE_TIME 3125.0e-6 // 3125 usec pause
#define BANG_OLUFSEN_R_PAUSE_TIME 6250.0e-6 // 6250 usec pause (repeat last bit)
#define BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME 12500.0e-6 // 12500 usec pause (trailer bit)
#define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define BANG_OLUFSEN_ADDRESS_OFFSET 0 // no address bits
#define BANG_OLUFSEN_ADDRESS_LEN 0 // no address bits
#define BANG_OLUFSEN_COMMAND_OFFSET 3 // skip startbits 2, 3, 4
#define BANG_OLUFSEN_COMMAND_LEN 16 // read 16 command bits
#define BANG_OLUFSEN_COMPLETE_DATA_LEN 20 // complete length: startbits 2, 3, 4 + 16 data bits + trailer bit
#define BANG_OLUFSEN_STOP_BIT 1 // has stop bit
#define BANG_OLUFSEN_LSB 0 // MSB...LSB
#define BANG_OLUFSEN_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* GRUNDIG & NOKIA
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define GRUNDIG_NOKIA_IR60_BIT_TIME 528.0e-6 // 528 usec pulse/pause
#define GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME 2639.0e-6 // 2639 usec pause after pre bit
#define GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // info frame repeat after 117.76 ms
#define GRUNDIG_NOKIA_IR60_STOP_BIT 0 // has no stop bit
#define GRUNDIG_NOKIA_IR60_LSB 1 // MSB...LSB
#define GRUNDIG_NOKIA_IR60_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags
#define GRUNDIG_FRAMES 2 // GRUNDIG sends each frame 1+1 times
#define GRUNDIG_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms
#define GRUNDIG_ADDRESS_OFFSET 0 // no address
#define GRUNDIG_ADDRESS_LEN 0 // no address
#define GRUNDIG_COMMAND_OFFSET 1 // skip 1 start bit
#define GRUNDIG_COMMAND_LEN 9 // read 9 command bits
#define GRUNDIG_COMPLETE_DATA_LEN 10 // complete length: 1 start bit + 9 data bits
#define NOKIA_FRAMES 3 // NOKIA sends each frame 1 + 1 + 1 times
#define NOKIA_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms
#define NOKIA_ADDRESS_OFFSET 9 // skip 9 bits (1 start bit + 8 data bits)
#define NOKIA_ADDRESS_LEN 8 // 7 address bits
#define NOKIA_COMMAND_OFFSET 1 // skip 1 bit (1 start bit)
#define NOKIA_COMMAND_LEN 8 // read 8 command bits
#define NOKIA_COMPLETE_DATA_LEN 17 // complete length: 1 start bit + 8 address bits + 8 command bits
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IR60:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IR60_FRAMES 2 // IR60 sends each frame 1+1 times
#define IR60_AUTO_REPETITION_PAUSE_TIME 22.2e-3 // repetition after 22.2ms
#define IR60_TIMEOUT_TIME 5000.0e-6 // timeout grundig frame, switch to IR60
#define IR60_ADDRESS_OFFSET 0 // skip 1 bits
#define IR60_ADDRESS_LEN 0 // read 0 address bits
#define IR60_COMMAND_OFFSET 0 // skip 1 bit (start bit after pre bit, always 1)
#define IR60_COMMAND_LEN 7 // read 6 command bits
#define IR60_COMPLETE_DATA_LEN 7 // complete length
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* SIEMENS & RUWIDO:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 275.0e-6 // 275 usec pulse
#define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause
#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 275.0e-6 // 275 usec short pulse
#define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 550.0e-6 // 550 usec long pulse
#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause
#define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause
#define SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define SIEMENS_OR_RUWIDO_STOP_BIT 0 // has no stop bit
#define SIEMENS_OR_RUWIDO_LSB 0 // MSB...LSB
#define SIEMENS_OR_RUWIDO_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags
#define RUWIDO_ADDRESS_OFFSET 0 // skip 0 bits
#define RUWIDO_ADDRESS_LEN 9 // read 9 address bits
#define RUWIDO_COMMAND_OFFSET 9 // skip 9 bits
#define RUWIDO_COMMAND_LEN 8 // read 7 + 1 command bits, last bit is only check bit
#define RUWIDO_COMPLETE_DATA_LEN 17 // complete length
#define SIEMENS_ADDRESS_OFFSET 0 // skip 0 bits
#define SIEMENS_ADDRESS_LEN 11 // read 11 bits
#define SIEMENS_COMMAND_OFFSET 11 // skip 11 bits
#define SIEMENS_COMMAND_LEN 11 // read 10 + 1 command bits, last bit is only check bit
#define SIEMENS_COMPLETE_DATA_LEN 22 // complete length
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* FDC:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define FDC_START_BIT_PULSE_TIME 2085.0e-6 // 2085 usec pulse
#define FDC_START_BIT_PAUSE_TIME 966.0e-6 // 966 usec pause
#define FDC_PULSE_TIME 300.0e-6 // 300 usec pulse
#define FDC_1_PAUSE_TIME 715.0e-6 // 715 usec pause
#define FDC_0_PAUSE_TIME 220.0e-6 // 220 usec pause
#define FDC_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms
#define FDC_ADDRESS_OFFSET 0 // skip 0 bits
#define FDC_ADDRESS_LEN 14 // read 14 address bits, but use only 6, shift 8 into command
#define FDC_COMMAND_OFFSET 20 // skip 20 bits
#define FDC_COMMAND_LEN 12 // read 12 bits
#define FDC_COMPLETE_DATA_LEN 40 // complete length
#define FDC_STOP_BIT 1 // has stop bit
#define FDC_LSB 1 // LSB...MSB
#define FDC_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RCCAR:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RCCAR_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse
#define RCCAR_START_BIT_PAUSE_TIME 2000.0e-6 // 2000 usec pause
#define RCCAR_PULSE_TIME 600.0e-6 // 360 usec pulse
#define RCCAR_1_PAUSE_TIME 450.0e-6 // 650 usec pause
#define RCCAR_0_PAUSE_TIME 900.0e-6 // 180 usec pause
#define RCCAR_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define RCCAR_ADDRESS_OFFSET 0 // skip 0 bits
#define RCCAR_ADDRESS_LEN 0 // read 0 address bits
#define RCCAR_COMMAND_OFFSET 0 // skip 0 bits
#define RCCAR_COMMAND_LEN 13 // read 13 bits
#define RCCAR_COMPLETE_DATA_LEN 13 // complete length
#define RCCAR_STOP_BIT 1 // has stop bit
#define RCCAR_LSB 1 // LSB...MSB
#define RCCAR_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* JVC:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define JVC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse
#define JVC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause
#define JVC_PULSE_TIME 560.0e-6 // 560 usec pulse
#define JVC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause
#define JVC_0_PAUSE_TIME 560.0e-6 // 560 usec pause
#define JVC_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms
#define JVC_ADDRESS_OFFSET 0 // skip 0 bits
#define JVC_ADDRESS_LEN 4 // read 4 address bits
#define JVC_COMMAND_OFFSET 4 // skip 4 bits
#define JVC_COMMAND_LEN 12 // read 12 bits
#define JVC_COMPLETE_DATA_LEN 16 // complete length
#define JVC_STOP_BIT 1 // has stop bit
#define JVC_LSB 1 // LSB...MSB
#define JVC_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* NIKON:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define NIKON_START_BIT_PULSE_TIME 2200.0e-6 // 2200 usec pulse
#define NIKON_START_BIT_PAUSE_TIME 27100.0e-6 // 27100 usec pause
#define NIKON_PULSE_TIME 500.0e-6 // 500 usec pulse
#define NIKON_1_PAUSE_TIME 3500.0e-6 // 3500 usec pause
#define NIKON_0_PAUSE_TIME 1500.0e-6 // 1500 usec pause
#define NIKON_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms
#define NIKON_ADDRESS_OFFSET 0 // skip 0 bits
#define NIKON_ADDRESS_LEN 0 // read 0 address bits
#define NIKON_COMMAND_OFFSET 0 // skip 0 bits
#define NIKON_COMMAND_LEN 2 // read 2 bits
#define NIKON_COMPLETE_DATA_LEN 2 // complete length
#define NIKON_STOP_BIT 1 // has stop bit
#define NIKON_LSB 0 // LSB...MSB
#define NIKON_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* KATHREIN:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define KATHREIN_START_BIT_PULSE_TIME 210.0e-6 // 1340 usec pulse
#define KATHREIN_START_BIT_PAUSE_TIME 6218.0e-6 // 340 usec pause
#define KATHREIN_1_PULSE_TIME 210.0e-6 // 1340 usec pulse
#define KATHREIN_1_PAUSE_TIME 3000.0e-6 // 340 usec pause
#define KATHREIN_0_PULSE_TIME 210.0e-6 // 500 usec pulse
#define KATHREIN_0_PAUSE_TIME 1400.0e-6 // 1300 usec pause
#define KATHREIN_SYNC_BIT_PAUSE_LEN_TIME 4600.0e-6 // 4600 usec sync (on 6th and/or 8th bit)
#define KATHREIN_FRAMES 1 // Kathrein sends 1 frame
#define KATHREIN_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms
#define KATHREIN_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms
#define KATHREIN_ADDRESS_OFFSET 1 // skip 1 bits
#define KATHREIN_ADDRESS_LEN 4 // read 4 address bits
#define KATHREIN_COMMAND_OFFSET 5 // skip 5 bits
#define KATHREIN_COMMAND_LEN 7 // read 7 bits
#define KATHREIN_COMPLETE_DATA_LEN 13 // complete length
#define KATHREIN_STOP_BIT 1 // has stop bit
#define KATHREIN_LSB 0 // MSB
#define KATHREIN_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* NETBOX:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define NETBOX_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse
#define NETBOX_START_BIT_PAUSE_TIME 800.0e-6 // 800 usec pause
#define NETBOX_PULSE_TIME 800.0e-6 // 800 usec pulse
#define NETBOX_PAUSE_TIME 800.0e-6 // 800 usec pause
#define NETBOX_FRAMES 1 // Netbox sends 1 frame
#define NETBOX_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms
#define NETBOX_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms
#define NETBOX_ADDRESS_OFFSET 0 // skip 0 bits
#define NETBOX_ADDRESS_LEN 3 // read 3 address bits
#define NETBOX_COMMAND_OFFSET 3 // skip 3 bits
#define NETBOX_COMMAND_LEN 13 // read 13 bits
#define NETBOX_COMPLETE_DATA_LEN 16 // complete length
#define NETBOX_STOP_BIT 0 // has no stop bit
#define NETBOX_LSB 1 // LSB
#define NETBOX_FLAGS IRMP_PARAM_FLAG_IS_SERIAL // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* LEGO:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define LEGO_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz)
#define LEGO_START_BIT_PAUSE_TIME 1026.0e-6 // 1026 usec pause (39 x 1/38kHz)
#define LEGO_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz)
#define LEGO_1_PAUSE_TIME 553.0e-6 // 553 usec pause (21 x 1/38kHz)
#define LEGO_0_PAUSE_TIME 263.0e-6 // 263 usec pause (10 x 1/38kHz)
#define LEGO_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define LEGO_ADDRESS_OFFSET 0 // skip 0 bits
#define LEGO_ADDRESS_LEN 0 // read 0 address bits
#define LEGO_COMMAND_OFFSET 0 // skip 0 bits
#define LEGO_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC)
#define LEGO_COMPLETE_DATA_LEN 16 // complete length
#define LEGO_STOP_BIT 1 // has stop bit
#define LEGO_LSB 0 // MSB...LSB
#define LEGO_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* THOMSON:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define THOMSON_PULSE_TIME 550.0e-6 // 550 usec pulse
#define THOMSON_1_PAUSE_TIME 4500.0e-6 // 4500 usec pause
#define THOMSON_0_PAUSE_TIME 2000.0e-6 // 2000 usec pause
#define THOMSON_FRAMES 1 // THOMSON sends 1 frame
#define THOMSON_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // repetition after 35ms
#define THOMSON_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms
#define THOMSON_ADDRESS_OFFSET 0 // skip 0 bits
#define THOMSON_ADDRESS_LEN 4 // read 4 address bits
#define THOMSON_COMMAND_OFFSET 5 // skip 4 address bits + 1 toggle bit
#define THOMSON_COMMAND_LEN 7 // read 7 command bits
#define THOMSON_COMPLETE_DATA_LEN 12 // complete length
#define THOMSON_STOP_BIT 1 // has stop bit
#define THOMSON_LSB 0 // MSB...LSB
#define THOMSON_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* BOSE:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define BOSE_START_BIT_PULSE_TIME 1060.0e-6 // 1060 usec pulse
#define BOSE_START_BIT_PAUSE_TIME 1425.0e-6 // 1425 usec pause
#define BOSE_PULSE_TIME 550.0e-6 // 550 usec pulse
#define BOSE_1_PAUSE_TIME 1425.0e-6 // 1425 usec pause
#define BOSE_0_PAUSE_TIME 437.0e-6 // 437 usec pause
#define BOSE_FRAMES 1
#define BOSE_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40ms?
#define BOSE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms?
#define BOSE_ADDRESS_OFFSET 0 // skip 0 bits
#define BOSE_ADDRESS_LEN 0 // read 16 address bits
#define BOSE_COMMAND_OFFSET 0 // skip 16 bits (8 address + 8 /address)
#define BOSE_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command)
#define BOSE_COMPLETE_DATA_LEN 16 // complete length
#define BOSE_STOP_BIT 1 // has stop bit
#define BOSE_LSB 1 // LSB...MSB
#define BOSE_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* A1TVBOX:
* In reality A1 TV Box has no start bit with 300/340 usec. There are 2 start bits "10" with 250us pulse + 150us pause + 150us pause + 250us pulse
* This is not very easy to detect, because 1st and 2nd pause of both start bits are closely spaced.
* So IRMP looks for pseudo start bit with 300/340 usec and ignores the second half of the 2nd bit (250us pulse)
* This method only works because the first data bit (which is the 3rd bit) following is always "1":
* IRMP treats the first "long" pulse (250us of 2nd start bit + 250us of 1st data bit) of this "1" as a first _short_ pulse.
* This is a bug in IRMP's manchester decoder, but a good feature here ;-)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define A1TVBOX_START_BIT_PULSE_TIME 300.0e-6 // 300 usec pulse
#define A1TVBOX_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause
#define A1TVBOX_BIT_PULSE_TIME 250.0e-6 // 250 usec pulse
#define A1TVBOX_BIT_PAUSE_TIME 150.0e-6 // 150 usec pulse
#define A1TVBOX_STOP_BIT 0 // has no stop bit
#define A1TVBOX_LSB 0 // MSB...LSB
#define A1TVBOX_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags
#define A1TVBOX_FRAMES 1 // A1TVBOX sends each frame 1 times
#define A1TVBOX_ADDRESS_OFFSET 1 // skip 1 bits
#define A1TVBOX_ADDRESS_LEN 8 // read 8 address bits
#define A1TVBOX_COMMAND_OFFSET 9 // skip 9 bits (start bit + address)
#define A1TVBOX_COMMAND_LEN 8 // read 8 command bits
#define A1TVBOX_COMPLETE_DATA_LEN 17 // complete length incl. start bit
#define A1TVBOX_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* MERLIN:
* See notes for A1TVBOX
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define MERLIN_START_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse
#define MERLIN_START_BIT_PAUSE_TIME 420.0e-6 // 429 usec pause
#define MERLIN_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse
#define MERLIN_BIT_PAUSE_TIME 210.0e-6 // 210 usec pulse
#define MERLIN_STOP_BIT 0 // has no stop bit
#define MERLIN_LSB 0 // MSB...LSB
#define MERLIN_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags
#define MERLIN_FRAMES 1 // MERLIN sends each frame 1 times
#define MERLIN_ADDRESS_OFFSET 2 // skip 1 bits
#define MERLIN_ADDRESS_LEN 9 // read 9 address bits
#define MERLIN_COMMAND_OFFSET 11 // skip 11 bits (start bit + address)
#define MERLIN_COMMAND_LEN 16 // read up to 16 command bits (could be up to 32)
#define MERLIN_COMPLETE_DATA_LEN 27 // complete length incl. start bit
#define MERLIN_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ORTEK (Hama): 6 address bits + 2 frame type bits + 6 command bits + 1 parity bit + 1 unknown bit + "1" + "0"
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define ORTEK_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse
#define ORTEK_START_BIT_PAUSE_TIME 1000.0e-6 // 1000 usec pause
#define ORTEK_BIT_TIME 500.0e-6 // 500 usec pulse/pause
#define ORTEK_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms
#define ORTEK_ADDRESS_OFFSET 0 // skip 0 bits
#define ORTEK_ADDRESS_LEN 8 // read 6 address bits + 2 special bits
#define ORTEK_COMMAND_OFFSET 8 // skip 6 address bits + 2 special bits
#define ORTEK_COMMAND_LEN 6 // read 6 command bits
#define ORTEK_COMPLETE_DATA_LEN 18 // complete length
#define ORTEK_STOP_BIT 0 // has no stop bit
#define ORTEK_LSB 0 // MSB...LSB
#define ORTEK_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* TELEFUNKEN:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define TELEFUNKEN_START_BIT_PULSE_TIME 600.0e-6 // 600 usec pulse
#define TELEFUNKEN_START_BIT_PAUSE_TIME 1500.0e-6 // 1500 usec pause
#define TELEFUNKEN_PULSE_TIME 600.0e-6 // 600 usec pulse
#define TELEFUNKEN_1_PAUSE_TIME 1500.0e-6 // 1500 usec pause
#define TELEFUNKEN_0_PAUSE_TIME 600.0e-6 // 600 usec pause
#define TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after XX ms ?????
#define TELEFUNKEN_ADDRESS_OFFSET 0 // skip 0 bits
#define TELEFUNKEN_ADDRESS_LEN 0 // read 0 address bits
#define TELEFUNKEN_COMMAND_OFFSET 0 // skip 0 bits
#define TELEFUNKEN_COMMAND_LEN 15 // read 15 bits
#define TELEFUNKEN_COMPLETE_DATA_LEN 15 // complete length
#define TELEFUNKEN_STOP_BIT 1 // has stop bit
#define TELEFUNKEN_LSB 0 // LSB...MSB
#define TELEFUNKEN_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ROOMBA
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define ROOMBA_START_BIT_PULSE_TIME 2790.0e-6 // 2790 usec pulse
#define ROOMBA_START_BIT_PAUSE_TIME 930.0e-6 // 930 usec pause
#define ROOMBA_0_PULSE_TIME 930.0e-6 // 930 usec pulse
#define ROOMBA_1_PULSE_TIME 2790.0e-6 // 2790 usec pulse
#define ROOMBA_0_PAUSE_TIME 2790.0e-6 // 2790 usec pause
#define ROOMBA_1_PAUSE_TIME 930.0e-6 // 930 usec pause
#define ROOMBA_FRAME_REPEAT_PAUSE_TIME 18.0e-3 // frame repeat after 18ms
#define ROOMBA_ADDRESS_OFFSET 0 // skip 0 bits
#define ROOMBA_ADDRESS_LEN 0 // read 0 address bits
#define ROOMBA_COMMAND_OFFSET 0 // skip 0 bits
#define ROOMBA_COMMAND_LEN 7 // read 7 bits
#define ROOMBA_COMPLETE_DATA_LEN 7 // complete length
#define ROOMBA_STOP_BIT 0 // has stop bit (fm: sure?)
#define ROOMBA_LSB 0 // MSB...LSB
#define ROOMBA_FLAGS 0 // flags
#define ROOMBA_FRAMES 8 // ROOMBA sends 8 frames (this is a lie, but more comfortable)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RC-MM (32, 24, or 12 bit)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RCMM32_START_BIT_PULSE_TIME 500.0e-6 // 500 usec pulse
#define RCMM32_START_BIT_PAUSE_TIME 220.0e-6 // 220 usec pause
#define RCMM32_PULSE_TIME 230.0e-6 // 230 usec pulse
#define RCMM32_00_PAUSE_TIME 220.0e-6 // 220 usec pause
#define RCMM32_01_PAUSE_TIME 370.0e-6 // 370 usec pause
#define RCMM32_10_PAUSE_TIME 540.0e-6 // 540 usec pause
#define RCMM32_11_PAUSE_TIME 720.0e-6 // 720 usec pause
#define RCMM32_FRAME_REPEAT_PAUSE_TIME 80.0e-3 // frame repeat after 80 ms
#define RCMM32_ADDRESS_OFFSET 0 // skip 0 bits
#define RCMM32_ADDRESS_LEN 16 // read 16 address bits
#define RCMM32_COMMAND_OFFSET 17 // skip 17 bits
#define RCMM32_COMMAND_LEN 15 // read 15 bits
#define RCMM32_COMPLETE_DATA_LEN 32 // complete length
#define RCMM32_STOP_BIT 1 // has stop bit
#define RCMM32_LSB 0 // LSB...MSB
#define RCMM32_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* PENTAX:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define PENTAX_START_BIT_PULSE_TIME 13000.0e-6 // 13 msec pulse
#define PENTAX_START_BIT_PAUSE_TIME 3000.0e-6 // 3 msec pause
#define PENTAX_PULSE_TIME 1000.0e-6 // 1 msec pulse
#define PENTAX_1_PAUSE_TIME 3000.0e-6 // 3 msec pause
#define PENTAX_0_PAUSE_TIME 1000.0e-6 // 1 msec pause
#define PENTAX_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms
#define PENTAX_ADDRESS_OFFSET 0 // skip 0 bits
#define PENTAX_ADDRESS_LEN 0 // read 0 address bits
#define PENTAX_COMMAND_OFFSET 0 // skip 0 bits
#define PENTAX_COMMAND_LEN 6 // read 6 bits
#define PENTAX_COMPLETE_DATA_LEN 6 // complete length
#define PENTAX_STOP_BIT 1 // has stop bit
#define PENTAX_LSB 0 // LSB...MSB
#define PENTAX_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ACP24: Stiebel Eltron ACP24 air conditioner
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define ACP24_START_BIT_PULSE_TIME 390.0e-6 // 390 usec pulse
#define ACP24_START_BIT_PAUSE_TIME 950.0e-6 // 950 usec pause
#define ACP24_PULSE_TIME 390.0e-6 // 390 usec pulse
#define ACP24_1_PAUSE_TIME 1300.0e-6 // 1300 usec pause
#define ACP24_0_PAUSE_TIME 950.0e-6 // 950 usec pause
#define ACP24_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms?
#define ACP24_ADDRESS_OFFSET 0 // skip 0 bits
#define ACP24_ADDRESS_LEN 0 // read 6 address bits
#define ACP24_COMMAND_OFFSET 0 // skip 6 bits
#define ACP24_COMMAND_LEN 0 // read 0 bits (70 bits will be read and compressed by special routine)
#define ACP24_COMPLETE_DATA_LEN 70 // complete length
#define ACP24_STOP_BIT 1 // has stop bit
#define ACP24_LSB 0 // LSB...MSB
#define ACP24_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IRMP16:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP16_START_BIT_PULSE_TIME 842.0e-6 // 842 usec pulse (32 x 1/38kHz)
#define IRMP16_START_BIT_PAUSE_TIME 1052.0e-6 // 1052 usec pause (40 x 1/38kHz)
#define IRMP16_PULSE_TIME 421.0e-6 // 421 usec pulse (16 x 1/38kHz)
#define IRMP16_1_PAUSE_TIME 842.0e-6 // 842 usec pause (32 x 1/38kHz)
#define IRMP16_0_PAUSE_TIME 421.0e-6 // 421 usec pause (16 x 1/38kHz)
#define IRMP16_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define IRMP16_ADDRESS_OFFSET 0 // skip 0 bits
#define IRMP16_ADDRESS_LEN 0 // read 0 address bits
#define IRMP16_COMMAND_OFFSET 0 // skip 0 bits
#define IRMP16_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC)
#define IRMP16_COMPLETE_DATA_LEN 16 // complete length
#define IRMP16_STOP_BIT 1 // has stop bit
#define IRMP16_LSB 1 // LSB...MSB
#define IRMP16_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* GREE - climate:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define GREE_START_BIT_PULSE_TIME 12000.0e-6 // 12000 usec pulse (32 x 1/38kHz)
#define GREE_START_BIT_PAUSE_TIME 6000.0e-6 // 6000 usec pause (40 x 1/38kHz)
#define GREE_PULSE_TIME 900.0e-6 // 900 usec pulse (16 x 1/38kHz)
#define GREE_1_PAUSE_TIME 700.0e-6 // 700 usec pause (32 x 1/38kHz)
#define GREE_0_PAUSE_TIME 2100.0e-6 // 2100 usec pause (16 x 1/38kHz)
#define GREE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms
#define GREE_ADDRESS_OFFSET 0 // skip 0 bits
#define GREE_ADDRESS_LEN 16 // read 16 address bits
#define GREE_COMMAND_OFFSET 16 // skip 16 bits
#define GREE_COMMAND_LEN 16 // read 16 bits
#define GREE_COMPLETE_DATA_LEN 32 // complete length
#define GREE_STOP_BIT 1 // has stop bit
#define GREE_LSB 1 // LSB...MSB
#define GREE_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* METZ:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define METZ_START_BIT_PULSE_TIME 870.0e-6 // 870 usec pulse
#define METZ_START_BIT_PAUSE_TIME 2300.0e-6 // 2300 usec pause
#define METZ_PULSE_TIME 435.0e-6 // 435 usec pulse
#define METZ_1_PAUSE_TIME 1680.0e-6 // 1680 usec pause
#define METZ_0_PAUSE_TIME 960.0e-6 // 960 usec pause
#define METZ_FRAME_REPEAT_PAUSE_TIME 122.0e-3 // frame repeat after 122ms
#define METZ_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit)
#define METZ_ADDRESS_LEN 6 // read 6 address bits
#define METZ_COMMAND_OFFSET 7 // skip 7 bits
#define METZ_COMMAND_LEN 13 // read 13 bits
#define METZ_COMPLETE_DATA_LEN 20 // complete length
#define METZ_STOP_BIT 0 // has no stop bit
#define METZ_LSB 0 // MSB...LSB
#define METZ_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RF GEN24 generic remote control (Pollin 550666, EAN 4049702006022 and many other similar RF remote controls)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RF_GEN24_0_PULSE_TIME 400.0e-6 // 400 usec pulse
#define RF_GEN24_0_PAUSE_TIME 1066.0e-6 // 1066 usec pause
#define RF_GEN24_1_PULSE_TIME 1066.0e-6 // 1066 usec pulse
#define RF_GEN24_1_PAUSE_TIME 400.0e-6 // 400 usec pause
#define RF_GEN24_FRAME_REPEAT_PAUSE_TIME 10.0e-3 // frame repeat after 10 msec
#define RF_GEN24_ADDRESS_OFFSET 0 // skip 0 bits
#define RF_GEN24_ADDRESS_LEN 10 // read 10 address bits
#define RF_GEN24_COMMAND_OFFSET 10 // skip 0 + 10 bits
#define RF_GEN24_COMMAND_LEN 14 // read 14 command bits
#define RF_GEN24_COMPLETE_DATA_LEN 24 // complete length
#define RF_GEN24_STOP_BIT 1 // has stop bit
#define RF_GEN24_LSB 0 // MSB...LSB
#define RF_GEN24_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RF X10 remote control (MEDION, Pollin 721815)
*
* Frame:
* 1 toggle bit + 7 checksum bits + 1 toggle bit + 7 command bits + 4 channel bits
*
* Rule:
* checksum = (command + 0x0055 + (channel << 4)) & 0x7F
*
* Here we store checksum in address, command incl. 4 channel bits in command
*
* In irmp_get_data():
* irmp_command = command << 4
* irmp_address = channel + 1
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RF_X10_START_BIT_PULSE_TIME 2850.0e-6 // 2850 usec pulse
#define RF_X10_START_BIT_PAUSE_TIME 1710.0e-6 // 1710 usec pulse
#define RF_X10_0_PULSE_TIME 570.0e-6 // 570 usec pulse
#define RF_X10_0_PAUSE_TIME 570.0e-6 // 570 usec pause
#define RF_X10_1_PULSE_TIME 570.0e-6 // 570 usec pulse
#define RF_X10_1_PAUSE_TIME 1710.0e-6 // 1710 usec pause
#define RF_X10_FRAME_REPEAT_PAUSE_TIME 4456.0e-6 // frame repeat after 4460 usec
#define RF_X10_ADDRESS_OFFSET 1 // skip 1st toggle bit
#define RF_X10_ADDRESS_LEN 7 // store 7 command bits in address
#define RF_X10_COMMAND_OFFSET 9 // skip 1st toggle bit + 7 command bits + 2nd toggle bit
#define RF_X10_COMMAND_LEN 11 // read 7 alternative command bits plus 4 0-bits
#define RF_X10_COMPLETE_DATA_LEN 20 // complete length
#define RF_X10_STOP_BIT 1 // has stop bit
#define RF_X10_LSB 0 // MSB...LSB
#define RF_X10_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* RF MEDION PC remote control (MEDION)
*
* Frame is simular to RF_X10, see above. Only the start bit timing differs.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define RF_MEDION_START_BIT_PULSE_TIME 3960.0e-6 // 3960 usec pulse
#define RF_MEDION_START_BIT_PAUSE_TIME 610.0e-6 // 610 usec pulse
#define RF_MEDION_0_PULSE_TIME 570.0e-6 // 570 usec pulse
#define RF_MEDION_0_PAUSE_TIME 570.0e-6 // 570 usec pause
#define RF_MEDION_1_PULSE_TIME 570.0e-6 // 570 usec pulse
#define RF_MEDION_1_PAUSE_TIME 1710.0e-6 // 1710 usec pause
#define RF_MEDION_FRAME_REPEAT_PAUSE_TIME 5000.0e-6 // frame repeat after 5000 usec
#define RF_MEDION_ADDRESS_OFFSET 1 // skip 1st toggle bit
#define RF_MEDION_ADDRESS_LEN 7 // store 7 command bits in address
#define RF_MEDION_COMMAND_OFFSET 9 // skip 1st toggle bit + 7 command bits + 2nd toggle bit
#define RF_MEDION_COMMAND_LEN 11 // read 7 alternative command bits plus 4 0-bits
#define RF_MEDION_COMPLETE_DATA_LEN 20 // complete length
#define RF_MEDION_STOP_BIT 1 // has stop bit
#define RF_MEDION_LSB 0 // MSB...LSB
#define RF_MEDION_FLAGS 0 // flags
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Frame Repetitions:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define AUTO_FRAME_REPETITION_TIME 80.0e-3 // SIRCS/SAMSUNG32/NUBERT: automatic repetition after 25-50ms
#endif // _IRMP_PROTOCOLS_H_
================================================
FILE: src/irmpprotocols.hpp
================================================
/*
* irmpprotocols.hpp - irmp protocols
*
* Copyright (C) 2020-2021 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef IRMP_PROTOCOLS_HPP
#define IRMP_PROTOCOLS_HPP
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IR protocol strings for IRMP and IRSND:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
const char proto_unknown[] PROGMEM = "UNKNOWN";
const char proto_sircs[] PROGMEM = "SIRCS";
const char proto_nec[] PROGMEM = "NEC";
const char proto_samsung[] PROGMEM = "SAMSUNG";
const char proto_matsushita[] PROGMEM = "MATSUSH";
const char proto_kaseikyo[] PROGMEM = "KASEIKYO";
const char proto_recs80[] PROGMEM = "RECS80";
const char proto_rc5[] PROGMEM = "RC5";
const char proto_denon[] PROGMEM = "DENON";
const char proto_rc6[] PROGMEM = "RC6";
const char proto_samsung32[] PROGMEM = "SAMSG32";
const char proto_apple[] PROGMEM = "APPLE";
const char proto_recs80ext[] PROGMEM = "RECS80EX";
const char proto_nubert[] PROGMEM = "NUBERT";
const char proto_bang_olufsen[] PROGMEM = "BANG OLU";
const char proto_grundig[] PROGMEM = "GRUNDIG";
const char proto_nokia[] PROGMEM = "NOKIA";
const char proto_siemens[] PROGMEM = "SIEMENS";
const char proto_fdc[] PROGMEM = "FDC";
const char proto_rccar[] PROGMEM = "RCCAR";
const char proto_jvc[] PROGMEM = "JVC";
const char proto_rc6a[] PROGMEM = "RC6A";
const char proto_nikon[] PROGMEM = "NIKON";
const char proto_ruwido[] PROGMEM = "RUWIDO";
const char proto_ir60[] PROGMEM = "IR60";
const char proto_kathrein[] PROGMEM = "KATHREIN";
const char proto_netbox[] PROGMEM = "NETBOX";
const char proto_nec16[] PROGMEM = "NEC16";
const char proto_nec42[] PROGMEM = "NEC42";
const char proto_lego[] PROGMEM = "LEGO";
const char proto_thomson[] PROGMEM = "THOMSON";
const char proto_bose[] PROGMEM = "BOSE";
const char proto_a1tvbox[] PROGMEM = "A1TVBOX";
const char proto_ortek[] PROGMEM = "ORTEK";
const char proto_telefunken[] PROGMEM = "TELEFUNKEN";
const char proto_roomba[] PROGMEM = "ROOMBA";
const char proto_rcmm32[] PROGMEM = "RCMM32";
const char proto_rcmm24[] PROGMEM = "RCMM24";
const char proto_rcmm12[] PROGMEM = "RCMM12";
const char proto_speaker[] PROGMEM = "SPEAKER";
const char proto_lgair[] PROGMEM = "LGAIR";
const char proto_samsung48[] PROGMEM = "SAMSG48";
const char proto_merlin[] PROGMEM = "MERLIN";
const char proto_pentax[] PROGMEM = "PENTAX";
const char proto_fan[] PROGMEM = "FAN";
const char proto_s100[] PROGMEM = "S100";
const char proto_acp24[] PROGMEM = "ACP24";
const char proto_technics[] PROGMEM = "TECHNICS";
const char proto_panasonic[] PROGMEM = "PANASONIC";
const char proto_mitsu_heavy[] PROGMEM = "MITSU_HEAVY";
const char proto_vincent[] PROGMEM = "VINCENT";
const char proto_samsungah[] PROGMEM = "SAMSUNGAH";
const char proto_irmp16[] PROGMEM = "IRMP16";
const char proto_gree[] PROGMEM = "GREE";
const char proto_rcii[] PROGMEM = "RCII";
const char proto_metz[] PROGMEM = "METZ";
const char proto_onkyo[] PROGMEM = "ONKYO";
const char proto_rf_gen24[] PROGMEM = "RF_GEN24";
const char proto_rf_x10[] PROGMEM = "RF_X10";
const char proto_rf_medion[] PROGMEM = "RF_MEDION";
const char proto_melinera[] PROGMEM = "MELINERA";
const char proto_rc6a20[] PROGMEM = "RC6A20";
const char proto_rc6a28[] PROGMEM = "RC6A28";
/*
* Must be in the same order as the Protocol numbers in irmpprotocols.h starting with IRMP_UNKNOWN_PROTOCOL = 0
*/
const char * const
irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM =
{
proto_unknown,
proto_sircs,
proto_nec,
proto_samsung,
proto_matsushita,
proto_kaseikyo,
proto_recs80,
proto_rc5,
proto_denon,
proto_rc6,
proto_samsung32,
proto_apple,
proto_recs80ext,
proto_nubert,
proto_bang_olufsen,
proto_grundig,
proto_nokia,
proto_siemens,
proto_fdc,
proto_rccar,
proto_jvc,
proto_rc6a,
proto_nikon,
proto_ruwido,
proto_ir60,
proto_kathrein,
proto_netbox,
proto_nec16,
proto_nec42,
proto_lego,
proto_thomson,
proto_bose,
proto_a1tvbox,
proto_ortek,
proto_telefunken,
proto_roomba,
proto_rcmm32,
proto_rcmm24,
proto_rcmm12,
proto_speaker,
proto_lgair,
proto_samsung48,
proto_merlin,
proto_pentax,
proto_fan,
proto_s100,
proto_acp24,
proto_technics,
proto_panasonic,
proto_mitsu_heavy,
proto_vincent,
proto_samsungah,
proto_irmp16,
proto_gree,
proto_rcii,
proto_metz,
proto_onkyo,
proto_rf_gen24,
proto_rf_x10,
proto_rf_medion,
proto_melinera,
proto_rc6a20,
proto_rc6a28
};
#endif // IRMP_PROTOCOLS_HPP
================================================
FILE: src/irmpsystem.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irmpsystem.h - system specific includes and defines
*
* Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRMPSYSTEM_H_
#define _IRMPSYSTEM_H_
#if !defined(_IRMP_H_) && !defined(_IRSND_H_)
# error please include only irmp.h or irsnd.h, not irmpsystem.h
#endif
#if defined(ARDUINO) // AVR Arduino. Should be first, since it covers multiple platforms
// to avoid the other includes and defines which are incompatible with ARDUINO
#elif defined(__18CXX) // Microchip PIC C18 compiler
# define PIC_C18
#elif defined(__XC8) // PIC XC8 compiler
# include
# define PIC_C18
#elif defined(__XC32) // XC32 or ChipKit compiler
# define PIC_XC32
#elif defined(__PCM__) || defined(__PCB__) || defined(__PCH__) // CCS PIC compiler
# define PIC_CCS
#elif defined(STM32L1XX_MD) || defined(STM32L1XX_MDP) || defined(STM32L1XX_HD) // ARM STM32
# include
# define ARM_STM32
# define ARM_STM32L1XX
# define F_CPU (SysCtlClockGet())
#elif defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) \
|| defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) \
|| defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) \
|| defined(STM32F10X_XL) || defined(STM32F10X_CL) // ARM STM32
# include
# define ARM_STM32
# define ARM_STM32F10X
# define F_CPU (SysCtlClockGet())
#elif defined(STM32F30X) // ARM STM32
# include
# define ARM_STM32
# define ARM_STM32F30X
# define F_CPU (SysCtlClockGet())
#elif defined(STM32F4XX) // ARM STM32
# include
# define ARM_STM32
# define ARM_STM32F4XX
# define F_CPU (SysCtlClockGet())
#elif defined(STM32L1) || defined(STM32F1) || defined(STM32F3) || defined(STM32F4) // ARM STM32 OPENCM3
# include
# include
# include
# include
# include
# include "../config.h"
# define ARM_STM32_OPENCM3
# define F_CPU rcc_ahb_frequency
#elif defined(USE_HAL_DRIVER) // ARM STM32 with HAL Library
# include "gpio.h"
# if defined(_IRSND_H_)
# include"tim.h"
# endif
# define ARM_STM32_HAL
# define F_CPU SystemCoreClock
#elif defined(__SDCC_stm8) // STM8
# define SDCC_STM8
#elif defined(TARGET_IS_BLIZZARD_RA2) // TI Stellaris (tested on Stellaris Launchpad with Code Composer Studio)
# define STELLARIS_ARM_CORTEX_M4
# define F_CPU (SysCtlClockGet())
#elif defined(__xtensa__) // ESP8266 (Arduino)
# include "Arduino.h"
# include "ets_sys.h"
# include "osapi.h"
# include "gpio.h"
# include "os_type.h"
# include "c_types.h"
# define uint_fast8_t uint8_t
# define uint_fast16_t uint16_t
#elif defined(TEENSYDUINO) && (defined(__MK20DX256__) || defined(__MK20DX128__)) // Teensy 3.x (tested on Teensy 3.1 in Arduino 1.6.5 / Teensyduino 1.2.5)
# include
# define TEENSY_ARM_CORTEX_M4
#elif defined(unix) || defined(WIN32) || defined(__APPLE__) // Unix/Linux or Windows or Apple
# define UNIX_OR_WINDOWS
#elif defined(__MBED__) // mbed platform
// #include "mbed.h" // if mbed.h is used, source must be compiled as cpp
#include "gpio_api.h"
#elif defined(IRMP_CHIBIOS_HAL) // ChibiOS HAL
# include "hal.h"
#elif defined(PICO_RP2040) // rp2040 with the pico-sdk
# include "hardware/clocks.h"
# include "hardware/pwm.h"
# include "pico/stdlib.h"
# define F_CPU (clock_get_hz(clk_sys))
#else
# define ATMEL_AVR // ATMEL AVR
#endif
#include
#if defined(UNIX_OR_WINDOWS) // Analyze on Unix/Linux or Windows
# include
# include
# define F_CPU 8000000L
# define ANALYZE
# include
# ifdef _MSC_VER
# define IRMP_PACKED_STRUCT
# endif
#endif
#if defined(ARDUINO) // AVR Arduino. Should be first, since it covers multiple platforms
// to avoid the other includes and defines which are incompatible with ARDUINO
#elif defined(ATMEL_AVR)
# include
# include
# include
# include
# include
# include
# define IRSND_OC2 0 // OC2
# define IRSND_OC2A 1 // OC2A
# define IRSND_OC2B 2 // OC2B
# define IRSND_OC0 3 // OC0
# define IRSND_OC0A 4 // OC0A
# define IRSND_OC0B 5 // OC0B
# define IRSND_XMEGA_OC0A 0 // OC0A
# define IRSND_XMEGA_OC0B 1 // OC0B
# define IRSND_XMEGA_OC0C 2 // OC0C
# define IRSND_XMEGA_OC0D 3 // OC0D
# define IRSND_XMEGA_OC1A 4 // OC1A
# define IRSND_XMEGA_OC1B 5 // OC1B
#elif defined(STELLARIS_ARM_CORTEX_M4)
# include "inc/hw_ints.h"
# include "inc/hw_memmap.h"
# include "inc/hw_types.h"
# include "inc/hw_gpio.h"
# include "driverlib/fpu.h"
# include "driverlib/sysctl.h"
# include "driverlib/interrupt.h"
# include "driverlib/gpio.h"
# include "driverlib/rom.h"
# include "driverlib/systick.h"
# include "driverlib/pin_map.h"
# include "driverlib/timer.h"
# define PROGMEM
# define memcpy_P memcpy
# define APP_SYSTICKS_PER_SEC 32
#elif defined(ARM_STM32F10X)
# include "stm32f10x_gpio.h"
# include "stm32f10x_rcc.h"
# include "stm32f10x_tim.h"
# include "misc.h"
# define PROGMEM
# define memcpy_P memcpy
#elif defined(SDCC_STM8)
# include "stm8s.h"
# define PROGMEM
# define memcpy_P memcpy
# define __attribute__(x)
# define uint_fast8_t uint8_t
# define uint_fast16_t uint16_t
#elif defined(TEENSY_ARM_CORTEX_M4)
# define PROGMEM
# define memcpy_P memcpy
#elif defined(__xtensa__)
# define PROGMEM
# define memcpy_P memcpy
#elif defined(__MBED__)
# define PROGMEM
# define memcpy_P memcpy
#else
# if ! defined(PROGMEM)
# define PROGMEM
# endif
# if ! defined(memcpy_P)
# define memcpy_P memcpy
# endif
#endif
#if defined(PIC_CCS) || defined(PIC_C18)
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned char uint_fast8_t;
typedef unsigned short uint_fast16_t;
#endif
#if defined (PIC_C18) // PIC C18 or XC8 compiler
# include // main PIC18 h file
#ifndef __XC8
# include // timer lib
# include // pwm lib
#endif
# define IRSND_PIC_CCP1 1 // PIC C18 RC2 = PWM1 module
# define IRSND_PIC_CCP2 2 // PIC C18 RC1 = PWM2 module
#endif
#if !defined(TRUE)
# define TRUE 1
# define FALSE 0
#endif
#if defined(PIC_XC32) // XC32 or ChipKit compiler
# include
# include
#endif
#if defined(PIC_C18)
# define IRMP_PACKED_STRUCT
#else
# if !defined(IRMP_PACKED_STRUCT)
# define IRMP_PACKED_STRUCT __attribute__ ((__packed__))
# endif
#endif
typedef struct IRMP_PACKED_STRUCT IRMP_DATA
{
uint8_t protocol; // protocol, e.g. IRMP_NEC_PROTOCOL
uint16_t address; // address
uint16_t command; // command
uint8_t flags; // flags, e.g. repetition
} IRMP_DATA;
#endif // _IRMPSYSTEM_H_
================================================
FILE: src/irsnd.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irsnd.h
*
* Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRSND_H_
#define _IRSND_H_
#include "irmpsystem.h"
#if !defined(IRSND_USE_AS_LIB)
# include "irsndconfig.h"
#endif
#if defined(ARDUINO)
# include "irsndArduinoExt.h"
#elif defined (ARM_STM32) // STM32
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRSND_PORT CONCAT(GPIO, IRSND_PORT_LETTER)
# if defined (ARM_STM32L1XX)
# define IRSND_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRSND_PORT_LETTER)
# define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER)
# elif defined (ARM_STM32F10X)
# define IRSND_PORT_RCC CONCAT(RCC_APB2Periph_GPIO, IRSND_PORT_LETTER)
# elif defined (ARM_STM32F30X)
# define IRSND_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRSND_PORT_LETTER)
# elif defined (ARM_STM32F4XX)
# define IRSND_PORT_RCC CONCAT(RCC_AHB1Periph_GPIO, IRSND_PORT_LETTER)
# define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER)
# endif
# define IRSND_BIT CONCAT(GPIO_Pin_, IRSND_BIT_NUMBER)
# define IRSND_TIMER CONCAT(TIM, IRSND_TIMER_NUMBER)
# define IRSND_TIMER_CHANNEL CONCAT(TIM_Channel_, IRSND_TIMER_CHANNEL_NUMBER)
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
# define IRSND_TIMER_RCC CONCAT(RCC_APB1Periph_TIM, IRSND_TIMER_NUMBER)
# elif (IRSND_TIMER_NUMBER == 1) || ((IRSND_TIMER_NUMBER >= 8) && (IRSND_TIMER_NUMBER <= 11))
# define IRSND_TIMER_RCC CONCAT(RCC_APB2Periph_TIM, IRSND_TIMER_NUMBER)
# else
# error IRSND_TIMER_NUMBER not valid.
# endif
# if !defined(USE_STDPERIPH_DRIVER)
# warning The STM32 port of IRSND uses the ST standard peripheral drivers which are not enabled in your build configuration.
# endif
#elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRSND_PORT CONCAT(GPIO, IRSND_PORT_LETTER)
# if defined (ARM_STM32L1)
# define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER)
# define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER)
# elif defined (STM32F1)
# define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER)
# elif defined (ARM_STM32F3)
# define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER)
# elif defined (ARM_STM32F4)
# define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER)
# define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER)
# endif
# define IRSND_BIT CONCAT(GPIO, IRSND_BIT_NUMBER)
# define IRSND_TIMER CONCAT(TIM, IRSND_TIMER_NUMBER)
# define IRSND_TIMER_CHANNEL CONCAT(TIM_OC, IRSND_TIMER_CHANNEL_NUMBER)
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
# define IRSND_TIMER_RCC CONCAT(RCC_TIM, IRSND_TIMER_NUMBER)
# elif (IRSND_TIMER_NUMBER == 1) || ((IRSND_TIMER_NUMBER >= 8) && (IRSND_TIMER_NUMBER <= 11))
# define IRSND_TIMER_RCC CONCAT(RCC_TIM, IRSND_TIMER_NUMBER)
# else
# error IRSND_TIMER_NUMBER not valid.
# endif
#elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
# define IRSND_BIT IRSND_BIT_NUMBER
#elif defined(PIC_C18)
# if defined(__12F1840)
// Do not change lines below unless you have a different HW. This example is for 12F1840
// setup macro for PWM used PWM module
//~ # define PWMon() TMR2=0,IRSND_PIN=1
//~ # define PWMoff() CCP1CON &=(~0b1100)
//~ # define PWMon() TMR2ON=1
//~ # define PWMoff() TMR2ON=0
#if defined(IRSND_DEBUG)
#define PWMon() LATA0=1
#define PWMoff() LATA0=0
#define IRSND_PIN LATA0
#else
# define PWMon() TMR2=0,CCP1CON |=0b1100
# define PWMoff() CCP1CON &=(~0b1100)
# define IRSND_PIN RA2
#endif
#else
// Do not change lines below until you have a different HW. Example is for 18F2550/18F4550
// setup macro for PWM used PWM module
# if IRSND_OCx == IRSND_PIC_CCP2
# define PWMon() TMR2=0,CCP2CON |=0b1100
# define PWMoff() CCP2CON &=(~0b1100)
# define IRSND_PIN TRISCbits.TRISC1 // RC1 = PWM2
# define SetDCPWM(x) SetDCPWM2(x)
# define ClosePWM ClosePWM2
# define OpenPWM(x) OpenPWM2(x)
# endif
# if IRSND_OCx == IRSND_PIC_CCP1
# define PWMon() TMR2=0,CCP1CON |=0b1100
# define PWMoff() CCP1CON &=(~0b1100)
# define IRSND_PIN TRISCbits.TRISC2 // RC2 = PWM1
# define SetDCPWM(x) SetDCPWM1(x)
# define ClosePWM ClosePWM1
# define OpenPWM(x) OpenPWM1(x)
# endif
# endif
# endif // PIC_C18
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000)
# undef IRSND_SUPPORT_SIEMENS_PROTOCOL
# define IRSND_SUPPORT_SIEMENS_PROTOCOL 0
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, A1TVBOX protocol disabled (should be at least 15000)
# undef IRSND_SUPPORT_A1TVBOX_PROTOCOL
# define IRSND_SUPPORT_A1TVBOX_PROTOCOL 0
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000)
# undef IRSND_SUPPORT_RECS80_PROTOCOL
# define IRSND_SUPPORT_RECS80_PROTOCOL 0
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000
# warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000)
# undef IRSND_SUPPORT_RECS80EXT_PROTOCOL
# define IRSND_SUPPORT_RECS80EXT_PROTOCOL 0
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 19000
# warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 19000)
# undef IRSND_SUPPORT_LEGO_PROTOCOL
# define IRSND_SUPPORT_LEGO_PROTOCOL 0
#endif
#include "irmpprotocols.h"
#define IRSND_NO_REPETITIONS 0 // no repetitions
#define IRSND_MAX_REPETITIONS 14 // max # of repetitions
#define IRSND_ENDLESS_REPETITION 15 // endless repetitions
#define IRSND_REPETITION_MASK 0x0F // lower nibble of flags
#define IRSND_RAW_REPETITION_FRAME 0x10 // send one or more raw repetition frames, yet only used for NEC
#define IRSND_SUPPRESS_TRAILER 0x20 // suppress trailer
#ifdef __cplusplus
extern "C"
{
#endif
extern void irsnd_init (void);
# ifdef __cplusplus
extern bool irsnd_is_busy (void);
extern bool irsnd_send_data (IRMP_DATA *, uint8_t);
extern bool irsnd_ISR (void);
#else
extern uint8_t irsnd_is_busy (void);
extern uint8_t irsnd_send_data (IRMP_DATA *, uint8_t);
extern uint8_t irsnd_ISR (void);
#endif
extern void irsnd_stop (void);
#if IRSND_USE_CALLBACK == 1
extern void irsnd_set_callback_ptr (void (*cb)(uint8_t));
#endif // IRSND_USE_CALLBACK == 1
#ifdef __cplusplus
}
#endif
#endif /* _IRSND_H_ */
================================================
FILE: src/irsnd.hpp
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* @file irsnd.c
*
* Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de
*
* Supported AVR mikrocontrollers:
*
* ATtiny87, ATtiny167
* ATtiny45, ATtiny85
* ATtiny44 ATtiny84
* ATtiny2313 ATtiny4313
* ATmega8, ATmega16, ATmega32
* ATmega162
* ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284, ATmega1284P
* ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#include "irsnd.h"
#if !defined(F_CPU)
# error F_CPU unkown
#endif
#define IRMP_NEC_REPETITION_PROTOCOL 0xFF // pseudo protocol: NEC repetition frame
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ATtiny pin definition of OC0A / OC0B
* ATmega pin definition of OC2 / OC2A / OC2B / OC0 / OC0A / OC0B
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) // ATtiny44/84 uses OC0A = PB2 or OC0B = PA7
# if IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 2
# elif IRSND_OCx == IRSND_OC0B // OC0B
# define IRSND_PORT_LETTER A
# define IRSND_BIT_NUMBER 7
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) // ATtiny45/85 uses OC0A = PB0 or OC0B = PB1
# if IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 0
# elif IRSND_OCx == IRSND_OC0B // OC0B
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 1
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATtiny2313__) || defined (__AVR_ATtiny4313__) // ATtiny2313/4313 uses OC0A = PB2 or OC0B = PD5
# if IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 2
# elif IRSND_OCx == IRSND_OC0B // OC0B
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 5
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__) // ATtiny87/167 uses OC0A = PA2
# if IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER A
# define IRSND_BIT_NUMBER 2
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC0A in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega8__) // ATmega8 uses only OC2 = PB3
# if IRSND_OCx == IRSND_OC2 // OC2
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 3
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC2 in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) // ATmega16|32 uses OC0 = PB3 or OC2 = PD7
# if IRSND_OCx == IRSND_OC2 // OC2
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 7
# elif IRSND_OCx == IRSND_OC0 // OC0
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 3
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC2 or IRSND_OC0 in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega162__) // ATmega162 uses OC2 = PB1 or OC0 = PB0
# if IRSND_OCx == IRSND_OC2 // OC2
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 1
# elif IRSND_OCx == IRSND_OC0 // OC0
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 0
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC2 or IRSND_OC0 in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega164__) \
|| defined (__AVR_ATmega324__) \
|| defined (__AVR_ATmega644__) \
|| defined (__AVR_ATmega644P__) \
|| defined (__AVR_ATmega1284__) \
|| defined (__AVR_ATmega1284P__) // ATmega164|324|644|644P|1284 uses OC2A = PD7 or OC2B = PD6 or OC0A = PB3 or OC0B = PB4
# if IRSND_OCx == IRSND_OC2A // OC2A
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 7
# elif IRSND_OCx == IRSND_OC2B // OC2B
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 6
# elif IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 3
# elif IRSND_OCx == IRSND_OC0B // OC0B
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 4
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega48__) \
|| defined (__AVR_ATmega88__) \
|| defined (__AVR_ATmega88P__) \
|| defined (__AVR_ATmega168__) \
|| defined (__AVR_ATmega168P__) \
|| defined (__AVR_ATmega328P__) // ATmega48|88|168|168|328 uses OC2A = PB3 or OC2B = PD3 or OC0A = PD6 or OC0B = PD5
# if IRSND_OCx == IRSND_OC2A // OC2A
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 3
# elif IRSND_OCx == IRSND_OC2B // OC2B
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 3
# elif IRSND_OCx == IRSND_OC0A // OC0A
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 6
# elif IRSND_OCx == IRSND_OC0B // OC0B
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 5
# else
# error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (__AVR_ATmega8515__) // ATmega8515 uses OC0 = PB0 or OC1A = PD5 or OC1B = PE2
# if IRSND_OCx == IRSND_OC0
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 0
# elif IRSND_OCx == IRSND_OC1A
# define IRSND_PORT_LETTER D
# define IRSND_BIT_NUMBER 5
# elif IRSND_OCx == IRSND_OC1B
# define IRSND_PORT_LETTER E
# define IRSND_BIT_NUMBER 2
# endif // IRSND_OCx
#elif defined (__AVR_XMEGA__) // ATxmega
# if IRSND_OCx == IRSND_XMEGA_OC0A
# define IRSND_BIT_NUMBER 0
# elif IRSND_OCx == IRSND_XMEGA_OC0B
# define IRSND_BIT_NUMBER 1
# elif IRSND_OCx == IRSND_XMEGA_OC0C
# define IRSND_BIT_NUMBER 2
# elif IRSND_OCx == IRSND_XMEGA_OC0D
# define IRSND_BIT_NUMBER 3
# elif IRSND_OCx == IRSND_XMEGA_OC1A
# define IRSND_BIT_NUMBER 4
# elif IRSND_OCx == IRSND_XMEGA_OC1B
# define IRSND_BIT_NUMBER 5
# else
# error Wrong value for IRSND_OCx, choose IRSND_XMEGA_OC0A, IRSND_XMEGA_OC0B, IRSND_XMEGA_OC0C, IRSND_XMEGA_OC0D, IRSND_XMEGA_OC1A, or IRSND_XMEGA_OC1B in irsndconfig.h
# endif // IRSND_OCx
#elif defined (PIC_C18) // Microchip C18 compiler
//Nothing here to do here -> See irsndconfig.h
#elif defined (ARM_STM32) // STM32
//Nothing here to do here -> See irsndconfig.h
#elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3
//Nothing here to do here -> See irsndconfig.h
#elif defined (ARM_STM32_HAL) // STM32 with Hal Library
//Nothing here to do here -> See irsndconfig.h
#elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
uint slice_num;
#elif defined (__xtensa__) // ESP8266
//Nothing here to do here -> See irsndconfig.h
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Macro digitalPinHasPWM bothers PIC_C18 compiler, but why?
*
* #elif defined (TEENSY_ARM_CORTEX_M4) // Teensy3
* # if !digitalPinHasPWM(IRSND_PIN)
* # error need pin with PWM output.
* # endif
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(ARDUINO)
// specified here to avoid else case
#else
# if !defined (unix) && !defined (WIN32)
# error mikrocontroller not defined, please fill in definitions here.
# endif // unix, WIN32
#endif // __AVR...
#if defined(__AVR_XMEGA__)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRSND_PORT IRSND_PORT_PRE.OUT
# define IRSND_DDR IRSND_PORT_PRE.DIR
# define IRSND_PIN IRSND_PORT_PRE.IN
# define IRSND_BIT IRSND_BIT_NUMBER
#elif defined(ATMEL_AVR)
# define _CONCAT(a,b) a##b
# define CONCAT(a,b) _CONCAT(a,b)
# define IRSND_PORT CONCAT(PORT, IRSND_PORT_LETTER)
# define IRSND_DDR CONCAT(DDR, IRSND_PORT_LETTER)
# define IRSND_BIT IRSND_BIT_NUMBER
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
typedef uint16_t IRSND_PAUSE_LEN;
#else
typedef uint8_t IRSND_PAUSE_LEN;
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* IR timings
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRSND_SIRCS_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME + 0.5)
#define IRSND_SIRCS_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_SIRCS_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME + 0.5)
#define IRSND_SIRCS_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME + 0.5)
#define IRSND_SIRCS_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME + 0.5)
#define IRSND_SIRCS_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SIRCS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_NEC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME + 0.5)
#define IRSND_NEC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_NEC_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_NEC_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME + 0.5)
#define IRSND_NEC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME + 0.5)
#define IRSND_NEC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME + 0.5)
#define IRSND_NEC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_MELINERA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_START_BIT_PULSE_TIME + 0.5)
#define IRSND_MELINERA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_MELINERA_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_MELINERA_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME + 0.5)
#define IRSND_MELINERA_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME + 0.5)
#define IRSND_MELINERA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME + 0.5)
#define IRSND_MELINERA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME + 0.5)
#define IRSND_MELINERA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MELINERA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SAMSUNG_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME + 0.5)
#define IRSND_SAMSUNG_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_SAMSUNG_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME + 0.5)
#define IRSND_SAMSUNG_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME + 0.5)
#define IRSND_SAMSUNG_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME + 0.5)
#define IRSND_SAMSUNG_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SAMSUNG32_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SAMSUNG32_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SAMSUNG48_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG48_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SAMSUNG48_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG48_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_MATSUSHITA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME + 0.5)
#define IRSND_MATSUSHITA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_MATSUSHITA_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME + 0.5)
#define IRSND_MATSUSHITA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME + 0.5)
#define IRSND_MATSUSHITA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME + 0.5)
#define IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MATSUSHITA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_KASEIKYO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME + 0.5)
#define IRSND_KASEIKYO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_KASEIKYO_PULSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME + 0.5)
#define IRSND_KASEIKYO_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME + 0.5)
#define IRSND_KASEIKYO_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME + 0.5)
#define IRSND_KASEIKYO_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * KASEIKYO_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_KASEIKYO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * KASEIKYO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_PANASONIC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME + 0.5)
#define IRSND_PANASONIC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_PANASONIC_PULSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME + 0.5)
#define IRSND_PANASONIC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME + 0.5)
#define IRSND_PANASONIC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME + 0.5)
#define IRSND_PANASONIC_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PANASONIC_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_PANASONIC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PANASONIC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_MITSU_HEAVY_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME + 0.5)
#define IRSND_MITSU_HEAVY_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_MITSU_HEAVY_PULSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME + 0.5)
#define IRSND_MITSU_HEAVY_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME + 0.5)
#define IRSND_MITSU_HEAVY_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME + 0.5)
#define IRSND_MITSU_HEAVY_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MITSU_HEAVY_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RECS80_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME + 0.5)
#define IRSND_RECS80_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_RECS80_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME + 0.5)
#define IRSND_RECS80_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME + 0.5)
#define IRSND_RECS80_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME + 0.5)
#define IRSND_RECS80_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RC5_START_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
#define IRSND_RC5_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5)
#define IRSND_RC5_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC5_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RC6_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME + 0.5)
#define IRSND_RC6_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_RC6_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_TIME + 0.5)
#define IRSND_RC6_BIT_2_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_2_TIME + 0.5)
#define IRSND_RC6_BIT_3_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_3_TIME + 0.5)
#define IRSND_RC6_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC6_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_DENON_PULSE_LEN (uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME + 0.5)
#define IRSND_DENON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME + 0.5)
#define IRSND_DENON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME + 0.5)
#define IRSND_DENON_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_DENON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_THOMSON_PULSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME + 0.5)
#define IRSND_THOMSON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME + 0.5)
#define IRSND_THOMSON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME + 0.5)
#define IRSND_THOMSON_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * THOMSON_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_THOMSON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * THOMSON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RECS80EXT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME + 0.5)
#define IRSND_RECS80EXT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_RECS80EXT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME + 0.5)
#define IRSND_RECS80EXT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME + 0.5)
#define IRSND_RECS80EXT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME + 0.5)
#define IRSND_RECS80EXT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80EXT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_TELEFUNKEN_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME + 0.5)
#define IRSND_TELEFUNKEN_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_TELEFUNKEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME + 0.5)
#define IRSND_TELEFUNKEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME + 0.5)
#define IRSND_TELEFUNKEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME + 0.5)
#define IRSND_TELEFUNKEN_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * TELEFUNKEN_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_BOSE_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME + 0.5)
#define IRSND_BOSE_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_BOSE_PULSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_PULSE_TIME + 0.5)
#define IRSND_BOSE_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME + 0.5)
#define IRSND_BOSE_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME + 0.5)
#define IRSND_BOSE_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BOSE_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_BOSE_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BOSE_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_NUBERT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME + 0.5)
#define IRSND_NUBERT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_NUBERT_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME + 0.5)
#define IRSND_NUBERT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME + 0.5)
#define IRSND_NUBERT_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME + 0.5)
#define IRSND_NUBERT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME + 0.5)
#define IRSND_NUBERT_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_NUBERT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_FAN_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME + 0.5)
#define IRSND_FAN_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_FAN_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME + 0.5)
#define IRSND_FAN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME + 0.5)
#define IRSND_FAN_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME + 0.5)
#define IRSND_FAN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME + 0.5)
#define IRSND_FAN_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FAN_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_FAN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FAN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SPEAKER_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME + 0.5)
#define IRSND_SPEAKER_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_SPEAKER_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME + 0.5)
#define IRSND_SPEAKER_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME + 0.5)
#define IRSND_SPEAKER_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME + 0.5)
#define IRSND_SPEAKER_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME + 0.5)
#define IRSND_SPEAKER_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SPEAKER_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SPEAKER_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SPEAKER_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_BANG_OLUFSEN_START_BIT1_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_START_BIT1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_START_BIT3_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_START_BIT3_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_R_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME + 0.5)
#define IRSND_BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME + 0.5)
#define IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME + 0.5)
#define IRSND_GRUNDIG_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_NOKIA_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NOKIA_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_IR60_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * IR60_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_SIEMENS_START_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME + 0.5)
#define IRSND_SIEMENS_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME + 0.5)
#define IRSND_SIEMENS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RUWIDO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME + 0.5)
#define IRSND_RUWIDO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_RUWIDO_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME + 0.5)
#define IRSND_RUWIDO_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME + 0.5)
#define IRSND_RUWIDO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_FDC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME + 0.5)
#define IRSND_FDC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_FDC_PULSE_LEN (uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME + 0.5)
#define IRSND_FDC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME + 0.5)
#define IRSND_FDC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME + 0.5)
#define IRSND_FDC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FDC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_RCCAR_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME + 0.5)
#define IRSND_RCCAR_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_RCCAR_PULSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME + 0.5)
#define IRSND_RCCAR_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME + 0.5)
#define IRSND_RCCAR_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME + 0.5)
#define IRSND_RCCAR_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RCCAR_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_JVC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME + 0.5)
#define IRSND_JVC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_JVC_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_JVC_PULSE_LEN (uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME + 0.5)
#define IRSND_JVC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME + 0.5)
#define IRSND_JVC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME + 0.5)
#define IRSND_JVC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_NIKON_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME + 0.5)
#define IRSND_NIKON_START_BIT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_NIKON_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_NIKON_PULSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME + 0.5)
#define IRSND_NIKON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME + 0.5)
#define IRSND_NIKON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME + 0.5)
#define IRSND_NIKON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_LEGO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME + 0.5)
#define IRSND_LEGO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_LEGO_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_LEGO_PULSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME + 0.5)
#define IRSND_LEGO_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME + 0.5)
#define IRSND_LEGO_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME + 0.5)
#define IRSND_LEGO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * LEGO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_IRMP16_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME + 0.5)
#define IRSND_IRMP16_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_IRMP16_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_IRMP16_PULSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME + 0.5)
#define IRSND_IRMP16_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME + 0.5)
#define IRSND_IRMP16_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME + 0.5)
#define IRSND_IRMP16_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * IRMP16_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_A1TVBOX_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME + 0.5)
#define IRSND_A1TVBOX_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_A1TVBOX_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME + 0.5)
#define IRSND_A1TVBOX_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME + 0.5)
#define IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * A1TVBOX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * A1TVBOX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_ROOMBA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME + 0.5)
#define IRSND_ROOMBA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_ROOMBA_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME + 0.5)
#define IRSND_ROOMBA_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME + 0.5)
#define IRSND_ROOMBA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME + 0.5)
#define IRSND_ROOMBA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME + 0.5)
#define IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * ROOMBA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_PENTAX_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME + 0.5)
#define IRSND_PENTAX_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_PENTAX_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_PENTAX_PULSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME + 0.5)
#define IRSND_PENTAX_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME + 0.5)
#define IRSND_PENTAX_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME + 0.5)
#define IRSND_PENTAX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PENTAX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#define IRSND_ACP24_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME + 0.5)
#define IRSND_ACP24_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_ACP24_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_REPEAT_START_BIT_PAUSE_TIME + 0.5)
#define IRSND_ACP24_PULSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_PULSE_TIME + 0.5)
#define IRSND_ACP24_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME + 0.5)
#define IRSND_ACP24_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME + 0.5)
#define IRSND_ACP24_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * ACP24_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t!
#if defined(PIC_C18) // PIC C18
# define IRSND_FREQ_TYPE uint8_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / 2 / Pre_Scaler / PIC_Scaler) - 1)
#elif defined (ARM_STM32) // STM32
# define IRSND_FREQ_TYPE uint32_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3
# define IRSND_FREQ_TYPE uint32_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#elif defined (ARM_STM32_HAL) // STM32 with Hal Library
# define IRSND_FREQ_TYPE uint32_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
# define IRSND_FREQ_TYPE uint32_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY
# define IRSND_FREQ_TYPE float
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#elif defined (__xtensa__) // ESP8266
# define IRSND_FREQ_TYPE float
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000)
#else // AVR
# if F_CPU >= 16000000L
# define AVR_PRESCALER 8
# else
# define AVR_PRESCALER 1
# endif
# define IRSND_FREQ_TYPE uint8_t
# define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / AVR_PRESCALER / 2) - 1)
# define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / AVR_PRESCALER / 2) - 1)
#endif
// @formatter:off
// Used for Arduino by IRTimer.hpp
volatile uint8_t irsnd_busy = 0;
volatile uint8_t irsnd_is_on = FALSE;
static volatile uint8_t irsnd_protocol = 0;
static volatile uint8_t irsnd_buffer[11] = { 0 };
static volatile uint8_t irsnd_repeat = 0;
static volatile uint8_t irsnd_suppress_trailer = 0;
// @formatter:on
#if defined(ARDUINO)
#include "irsndArduinoExt.hpp" // must be after the declarations of irsnd_busy etc.
#else
#if IRSND_USE_CALLBACK == 1
static void (*irsnd_callback_ptr) (uint8_t);
#endif // IRSND_USE_CALLBACK == 1
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Switch PWM on
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
static void
irsnd_on (void)
{
if (! irsnd_is_on)
{
#if !defined(ANALYZE)
# if defined(PIC_C18) // PIC C18
PWMon();
// IRSND_PIN = 0; // output mode -> enable PWM outout pin (0=PWM on, 1=PWM off)
# elif defined (ARM_STM32) // STM32
IRSND_TIMER->EGR = TIM_PSCReloadMode_Immediate; // Generate an update event to reload the Prescaler and the Repetition counter values immediately
TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Enable); // enable OC-output (is being disabled in TIM_SelectOCxM())
TIM_Cmd(IRSND_TIMER, ENABLE); // enable counter
# elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3
TIM_EGR(IRSND_TIMER) = TIM_EGR_UG; // Generate an update event to reload the Prescaler and the Repetition counter values immediately
timer_enable_oc_output(IRSND_TIMER, IRSND_TIMER_CHANNEL); // enable OC-output
timer_enable_counter(IRSND_TIMER); // enable counter
# elif defined (ARM_STM32_HAL) // STM32 with Hal Library
IRSND_TIMER->EGR = TIM_EGR_UG; // Generate an update event to reload the Prescaler and the Repetition counter values immediately
HAL_TIM_PWM_Start(&IRSND_TIMER_HANDLER, IRSND_TIMER_CHANNEL_NUMBER);
# elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
pwm_set_counter(slice_num, 0); // reset counter
pwm_set_enabled(slice_num, true); // enable counter
gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_NORMAL);
# elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY
analogWrite(IRSND_PIN, 33 * 255 / 100); // pwm 33%
# elif defined (__xtensa__) // ESP8266 (Arduino)
analogWrite(IRSND_PIN, 33 * 1023 / 100); // pwm 33%
# elif defined (__AVR_XMEGA__)
# if (IRSND_OCx == IRSND_XMEGA_OC0A) // use OC0A
XMEGA_Timer.CTRLB |= (1< disbale PWM output pin (0=PWM on, 1=PWM off)
# elif defined (ARM_STM32) // STM32
TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Disable); // disable OC-output
TIM_Cmd(IRSND_TIMER, DISABLE); // disable counter
# elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3
timer_disable_oc_output(IRSND_TIMER, IRSND_TIMER_CHANNEL); // disable OC-output
timer_disable_counter(IRSND_TIMER); // disable counter
# elif defined (ARM_STM32_HAL) // STM32
HAL_TIM_PWM_Stop(&IRSND_TIMER_HANDLER, IRSND_TIMER_CHANNEL_NUMBER);
# elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
pwm_set_enabled(slice_num, false); // disable counter
gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_LOW); // set IRSND_BIT to low
# elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY
analogWrite(IRSND_PIN, 0); // pwm off, LOW level
# elif defined (__xtensa__) // ESP8266
analogWrite(IRSND_PIN, 0); // pwm off, LOW level
# elif defined (__AVR_XMEGA__)
# if (IRSND_OCx == IRSND_XMEGA_OC0A) // use OC0A
XMEGA_Timer.CTRLB &= ~(1<
#endif
static void
irsnd_set_freq (IRSND_FREQ_TYPE freq)
{
#if !defined(ANALYZE)
# if defined(PIC_C18) // PIC C18 or XC8
# if defined(__12F1840) // XC8
TRISA2=0;
PR2=freq;
CCP1M0=1;
CCP1M1=1;
CCP1M2=1;
CCP1M3=1;
DC1B0=1;
DC1B1=0;
CCPR1L = 0b01101001;
TMR2IF = 0;
TMR2ON=1;
CCP1CON &=(~0b0011); // p 197 "active high"
# else // PIC C18
OpenPWM(freq);
SetDCPWM( (uint16_t) (freq * 2) + 1); // freq*2 = Duty cycles 50%
# endif
PWMoff();
# elif defined (ARM_STM32) // STM32
static uint32_t TimeBaseFreq = 0;
if (TimeBaseFreq == 0)
{
RCC_ClocksTypeDef RCC_ClocksStructure;
/* Get system clocks and store timer clock in variable */
RCC_GetClocksFreq(&RCC_ClocksStructure);
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
if (RCC_ClocksStructure.PCLK1_Frequency == RCC_ClocksStructure.HCLK_Frequency)
{
TimeBaseFreq = RCC_ClocksStructure.PCLK1_Frequency;
}
else
{
TimeBaseFreq = RCC_ClocksStructure.PCLK1_Frequency * 2;
}
# else
if (RCC_ClocksStructure.PCLK2_Frequency == RCC_ClocksStructure.HCLK_Frequency)
{
TimeBaseFreq = RCC_ClocksStructure.PCLK2_Frequency;
}
else
{
TimeBaseFreq = RCC_ClocksStructure.PCLK2_Frequency * 2;
}
# endif
}
freq = TimeBaseFreq/freq;
/* Set frequency */
TIM_SetAutoreload(IRSND_TIMER, freq - 1);
/* Set duty cycle */
TIM_SetCompare1(IRSND_TIMER, freq / 2);
# elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3
static uint32_t TimeBaseFreq = 0;
if (TimeBaseFreq == 0)
{
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
if (rcc_apb1_frequency == rcc_ahb_frequency)
{
TimeBaseFreq = rcc_apb1_frequency;
}
else
{
TimeBaseFreq = rcc_apb1_frequency * 2;
}
# else
if (rcc_apb2_frequency == rcc_ahb_frequency)
{
TimeBaseFreq = rcc_apb2_frequency;
}
else
{
TimeBaseFreq = rcc_apb2_frequency * 2;
}
# endif
}
freq = TimeBaseFreq/freq;
/* Set frequency */
timer_set_period(IRSND_TIMER, freq - 1);
/* Set duty cycle */
timer_set_oc_value(IRSND_TIMER, TIM_OC1, freq / 2);
# elif defined (ARM_STM32_HAL) // STM32 with Hal Library
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
uint32_t uwPrescalerValue = (uint32_t) ((IRSND_TIMER_SPEED_APBX) / (freq*10)) - 1; //1kHz
//IRSND_TIMER_HANDLER.Instance = TIM2;
IRSND_TIMER_HANDLER.Init.Prescaler = uwPrescalerValue;
IRSND_TIMER_HANDLER.Init.CounterMode = TIM_COUNTERMODE_UP;
IRSND_TIMER_HANDLER.Init.Period = 10 -1;
IRSND_TIMER_HANDLER.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
IRSND_TIMER_HANDLER.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&IRSND_TIMER_HANDLER) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&IRSND_TIMER_HANDLER, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = IRSND_TIMER_HANDLER.Init.Period / 2;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&IRSND_TIMER_HANDLER, &sConfigOC, IRSND_TIMER_CHANNEL_NUMBER ) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
# elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
static uint32_t TimeBaseFreq = 0;
if (TimeBaseFreq == 0)
{
TimeBaseFreq = F_CPU;
}
freq = TimeBaseFreq/freq;
/* Set frequency */
pwm_set_wrap(slice_num, freq - 1);
/* Set duty cycle */
pwm_set_gpio_level(IRSND_BIT, freq / 2);
# elif defined (TEENSY_ARM_CORTEX_M4)
analogWriteResolution(8); // 8 bit
analogWriteFrequency(IRSND_PIN, freq);
analogWrite(IRSND_PIN, 0); // pwm off, LOW level
#elif defined (__xtensa__)
// analogWriteRange(255);
analogWriteFreq(freq);
analogWrite(IRSND_PIN, 0); // pwm off, LOW level
# elif defined (__AVR_XMEGA__)
XMEGA_Timer.CCA = freq;
# else // AVR
# if IRSND_OCx == IRSND_OC2
OCR2 = freq; // use register OCR2 for OC2
# elif IRSND_OCx == IRSND_OC2A // use OC2A
OCR2A = freq; // use register OCR2A for OC2A and OC2B!
# elif IRSND_OCx == IRSND_OC2B // use OC2B
OCR2A = freq; // use register OCR2A for OC2A and OC2B!
# elif IRSND_OCx == IRSND_OC0 // use OC0
OCR0 = freq; // use register OCR2 for OC2
# elif IRSND_OCx == IRSND_OC0A // use OC0A
OCR0A = freq; // use register OCR0A for OC0A and OC0B!
# elif IRSND_OCx == IRSND_OC0B // use OC0B
OCR0A = freq; // use register OCR0A for OC0A and OC0B!
# else
# error wrong value of IRSND_OCx
# endif
# endif //PIC_C18
#endif // ANALYZE
}
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Initialize the PWM
* @details Configures 0CR0A, 0CR0B and 0CR2B as PWM channels
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
void
irsnd_init (void)
{
#if !defined(ANALYZE)
# if defined(PIC_C18) // PIC C18 or XC8 compiler
# if ! defined(__12F1840) // only C18:
OpenTimer;
# endif
irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency
IRSND_PIN = 0; // set IO to outout
PWMoff();
# elif defined (ARM_STM32) // STM32
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* GPIOx clock enable */
# if defined (ARM_STM32L1XX)
RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE);
# elif defined (ARM_STM32F10X)
RCC_APB2PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // only in case of remapping, not necessary for default port-timer mapping
# elif defined (ARM_STM32F30X)
RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE);
# elif defined (ARM_STM32F4XX)
RCC_AHB1PeriphClockCmd(IRSND_PORT_RCC, ENABLE);
# endif
/* GPIO Configuration */
GPIO_InitStructure.GPIO_Pin = IRSND_BIT;
# if defined (ARM_STM32L1XX) || defined (ARM_STM32F4XX)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IRSND_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(IRSND_PORT, (uint8_t)IRSND_BIT_NUMBER, IRSND_GPIO_AF);
# elif defined (ARM_STM32F10X)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(IRSND_PORT, &GPIO_InitStructure);
// GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], ENABLE); // only in case of remapping, not necessary for default port-timer mapping
# elif defined (ARM_STM32F30X)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IRSND_PORT, &GPIO_InitStructure);
// GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], ENABLE); // only in case of remapping, not necessary for default port-timer mapping
# endif
/* TIMx clock enable */
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
RCC_APB1PeriphClockCmd(IRSND_TIMER_RCC, ENABLE);
# else
RCC_APB2PeriphClockCmd(IRSND_TIMER_RCC, ENABLE);
# endif
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = -1; // set dummy value (don't set to 0), will be initialized later
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(IRSND_TIMER, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // will be initialized later
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(IRSND_TIMER, &TIM_OCInitStructure);
/* Preload configuration */
TIM_ARRPreloadConfig(IRSND_TIMER, ENABLE);
TIM_OC1PreloadConfig(IRSND_TIMER, TIM_OCPreload_Enable);
irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency
# elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3
/* GPIOx clock enable */
# if defined (STM32L1) || defined (STM32F1) || defined (STM32F3) || defined (STM32F4)
rcc_periph_clock_enable(IRSND_PORT_RCC);
# endif
/* GPIO Configuration */
# if defined (STM32L) || defined (STM32F4)
gpio_mode_setup(IRSND_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IRSND_BIT);
gpio_set_output_options(IRSND_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRSND_BIT);
gpio_set_af(IRSND_PORT, IRSND_GPIO_AF, (uint8_t)IRSND_BIT_NUMBER);
# elif defined (STM32F1)
gpio_set_mode(IRSND_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, IRSND_BIT);
# elif defined (STM32F3)
gpio_mode_setup(IRSND_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IRSND_BIT);
gpio_set_output_options(IRSND_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRSND_BIT);
//gpio_set_af(IRSND_PORT, IRSND_GPIO_AF, (uint8_t)IRSND_BIT_NUMBER);
# endif
/* TIMx clock enable */
# if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14))
rcc_periph_clock_enable(IRSND_TIMER_RCC);
# else
rcc_periph_clock_enable(IRSND_TIMER_RCC);
# endif
/* Time base configuration */
timer_set_mode(IRSND_TIMER, 0, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(IRSND_TIMER, -1); // set dummy value (don't set to 0), will be initialized later
timer_set_prescaler(IRSND_TIMER, 0);
/* PWM1 Mode configuration */
timer_set_oc_mode(IRSND_TIMER, TIM_OC1, TIM_OCM_PWM1);
timer_enable_oc_output(IRSND_TIMER, TIM_OC1);
timer_set_oc_value(IRSND_TIMER, TIM_OC1, 0); // will be initialized later
timer_set_oc_polarity_high(IRSND_TIMER, TIM_OC1);
/* Preload configuration */
timer_enable_preload(IRSND_TIMER);
timer_enable_oc_preload(IRSND_TIMER, TIM_OC1);
irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency
# elif defined (ARM_STM32_HAL)
irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency
# elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040
/* GPIO Configuration */
gpio_set_function(IRSND_BIT, GPIO_FUNC_PWM);
slice_num = pwm_gpio_to_slice_num(IRSND_BIT);
pwm_set_output_polarity(slice_num, true, true);
gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_LOW);
irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency
# elif defined (TEENSY_ARM_CORTEX_M4)
if (!digitalPinHasPWM(IRSND_PIN))
{
return;
}
# elif defined (__xtensa__)
pinMode(IRSND_PIN, OUTPUT);
irsnd_set_freq (IRSND_FREQ_36_KHZ);
# elif defined (__AVR_XMEGA__)
IRSND_PORT &= ~(1<>= 1;
len--;
}
return xx;
}
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
static uint8_t sircs_additional_bitlen;
#endif // IRSND_SUPPORT_SIRCS_PROTOCOL == 1
/**
* @param do_wait - true: Wait for last command to have ended sending its trailing space before start of new sending.
* For Arduino: Additionally wait for sent command to have ended (including trailing gap).
* false: Return directly and do sending in background.
* Keep in mind not to send next frame in background before this frame and its trailing space has ended!
* @return false if protocol was not found or do_wait was false and sending (of former frame and its trailing space) is still in progress.
*/
# ifdef __cplusplus
bool
#else
uint8_t
#endif
irsnd_send_data(IRMP_DATA *irmp_data_p, uint8_t do_wait)
{
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
static uint8_t toggle_bit_recs80;
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
static uint8_t toggle_bit_recs80ext;
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
static uint8_t toggle_bit_rc5;
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1
static uint8_t toggle_bit_rc6;
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
static uint8_t toggle_bit_thomson;
#endif
uint16_t address;
uint16_t command;
// to avoid [-Wunused-variable] compiler warnings, e.g. if only NUBERT is activated.
(void) address;
(void) command;
if (do_wait)
{
while (irsnd_busy)
{
// wait for last command to have ended
}
}
else if (irsnd_busy)
{
// Here we do not want to wait, but sending is still in progress and we may overwrite current frame data if not returning here.
return (FALSE);
}
irsnd_protocol = irmp_data_p->protocol;
irsnd_repeat = irmp_data_p->flags & IRSND_REPETITION_MASK;
#if !defined(ARDUINO) // never send a trailing space for Arduino
irsnd_suppress_trailer = (irmp_data_p->flags & IRSND_SUPPRESS_TRAILER) ? TRUE : FALSE;
#endif
switch (irsnd_protocol)
{
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
case IRMP_SIRCS_PROTOCOL:
{
// uint8_t sircs_additional_command_len;
uint8_t sircs_additional_address_len;
sircs_additional_bitlen = (irmp_data_p->address & 0xFF00) >> 8; // additional bitlen
if (sircs_additional_bitlen > 15 - SIRCS_MINIMUM_DATA_LEN)
{
// sircs_additional_command_len = 15 - SIRCS_MINIMUM_DATA_LEN;
sircs_additional_address_len = sircs_additional_bitlen - (15 - SIRCS_MINIMUM_DATA_LEN);
}
else
{
// sircs_additional_command_len = sircs_additional_bitlen;
sircs_additional_address_len = 0;
}
command = bitsrevervse (irmp_data_p->command, 15);
irsnd_buffer[0] = (command & 0x7F80) >> 7; // CCCCCCCC
irsnd_buffer[1] = (command & 0x007F) << 1; // CCCC****
if (sircs_additional_address_len > 0)
{
address = bitsrevervse (irmp_data_p->address, 5);
irsnd_buffer[1] |= (address & 0x0010) >> 4;
irsnd_buffer[2] = (address & 0x000F) << 4;
}
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
case IRMP_APPLE_PROTOCOL:
{
command = irmp_data_p->command | (irmp_data_p->address << 8); // store address as ID in upper byte of command
address = 0x87EE; // set fixed NEC-lookalike address (customer ID of apple)
address = bitsrevervse (address, NEC_ADDRESS_LEN);
command = bitsrevervse (command, NEC_COMMAND_LEN);
irsnd_protocol = IRMP_NEC_PROTOCOL; // APPLE protocol is NEC with id instead of inverted command
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[3] = (command & 0x00FF); // cccccccc (ID)
irsnd_busy = TRUE;
break;
}
case IRMP_NEC_PROTOCOL:
{
if (irmp_data_p->flags & IRSND_RAW_REPETITION_FRAME)
{
irsnd_protocol = IRMP_NEC_REPETITION_PROTOCOL; // send a raw repetition frame
irsnd_buffer[0] = 0x00; // no address, no command
}
else
{
address = bitsrevervse (irmp_data_p->address, NEC_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, NEC_COMMAND_LEN);
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[3] = ~((command & 0xFF00) >> 8); // cccccccc
}
irsnd_busy = TRUE;
break;
}
case IRMP_ONKYO_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, NEC_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, NEC_COMMAND_LEN);
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[3] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
case IRMP_NEC16_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, NEC16_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, NEC16_COMMAND_LEN);
irsnd_buffer[0] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NEC42_PROTOCOL == 1
case IRMP_NEC42_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, NEC42_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, NEC42_COMMAND_LEN);
irsnd_buffer[0] = ( (address & 0x1FE0) >> 5); // AAAAAAAA
irsnd_buffer[1] = ( (address & 0x001F) << 3) | ((~address & 0x1C00) >> 10); // AAAAAaaa
irsnd_buffer[2] = ((~address & 0x03FC) >> 2); // aaaaaaaa
irsnd_buffer[3] = ((~address & 0x0003) << 6) | ( (command & 0x00FC) >> 2); // aaCCCCCC
irsnd_buffer[4] = ( (command & 0x0003) << 6) | ((~command & 0x00FC) >> 2); // CCcccccc
irsnd_buffer[5] = ((~command & 0x0003) << 6); // cc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_MELINERA_PROTOCOL == 1
case IRMP_MELINERA_PROTOCOL:
{
command = irmp_data_p->command;
irsnd_buffer[0] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_LGAIR_PROTOCOL == 1
case IRMP_LGAIR_PROTOCOL:
{
address = irmp_data_p->address;
command = irmp_data_p->command;
irsnd_buffer[0] = ( (address & 0x00FF)); // AAAAAAAA
irsnd_buffer[1] = ( (command & 0xFF00) >> 8); // CCCCCCCC
irsnd_buffer[2] = ( (command & 0x00FF)); // CCCCCCCC
irsnd_buffer[3] = (( ((command & 0xF000) >> 12) + // checksum
((command & 0x0F00) >> 8) +
((command & 0x00F0) >>4 ) +
((command & 0x000F))) & 0x000F) << 4;
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
case IRMP_SAMSUNG_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, SAMSUNG_COMMAND_LEN);
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = (command & 0x00F0) | ((command & 0xF000) >> 12); // IIIICCCC
irsnd_buffer[3] = ((command & 0x0F00) >> 4) | ((~(command & 0xF000) >> 12) & 0x0F); // CCCCcccc
irsnd_buffer[4] = (~(command & 0x0F00) >> 4) & 0xF0; // cccc0000
irsnd_busy = TRUE;
break;
}
case IRMP_SAMSUNG32_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, SAMSUNG32_COMMAND_LEN);
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[3] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1
case IRMP_SAMSUNG48_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, 16);
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = ((command & 0xFF00) >> 8); // CCCCCCCC
irsnd_buffer[3] = ~((command & 0xFF00) >> 8); // cccccccc
irsnd_buffer[4] = (command & 0x00FF); // CCCCCCCC
irsnd_buffer[5] = ~(command & 0x00FF); // cccccccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
case IRMP_MATSUSHITA_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, MATSUSHITA_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, MATSUSHITA_COMMAND_LEN);
irsnd_buffer[0] = (command & 0x0FF0) >> 4; // CCCCCCCC
irsnd_buffer[1] = ((command & 0x000F) << 4) | ((address & 0x0F00) >> 8); // CCCCAAAA
irsnd_buffer[2] = (address & 0x00FF); // AAAAAAAA
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1
case IRMP_TECHNICS_PROTOCOL:
{
command = bitsrevervse (irmp_data_p->command, TECHNICS_COMMAND_LEN);
irsnd_buffer[0] = (command & 0x07FC) >> 3; // CCCCCCCC
irsnd_buffer[1] = ((command & 0x0007) << 5) | ((~command & 0x07C0) >> 6); // CCCccccc
irsnd_buffer[2] = (~command & 0x003F) << 2; // cccccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1
case IRMP_KASEIKYO_PROTOCOL:
{
uint8_t xor_value;
uint16_t genre2;
address = bitsrevervse (irmp_data_p->address, KASEIKYO_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, KASEIKYO_COMMAND_LEN + 4);
genre2 = bitsrevervse ((irmp_data_p->flags & ~IRSND_REPETITION_MASK) >> 4, 4);
xor_value = ((address & 0x000F) ^ ((address & 0x00F0) >> 4) ^ ((address & 0x0F00) >> 8) ^ ((address & 0xF000) >> 12)) & 0x0F;
irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[2] = xor_value << 4 | (command & 0x000F); // XXXXCCCC
irsnd_buffer[3] = (genre2 << 4) | (command & 0xF000) >> 12; // ggggCCCC
irsnd_buffer[4] = (command & 0x0FF0) >> 4; // CCCCCCCC
xor_value = irsnd_buffer[2] ^ irsnd_buffer[3] ^ irsnd_buffer[4];
irsnd_buffer[5] = xor_value;
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1
case IRMP_PANASONIC_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, PANASONIC_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, PANASONIC_COMMAND_LEN);
irsnd_buffer[0] = 0x40; // 01000000
irsnd_buffer[1] = 0x04; // 00000100
irsnd_buffer[2] = 0x01; // 00000001
irsnd_buffer[3] = (address & 0xFF00) >> 8; // AAAAAAAA
irsnd_buffer[4] = (address & 0x00FF); // AAAAAAAA
irsnd_buffer[5] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[6] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
case IRMP_MITSU_HEAVY_PROTOCOL:
{
address = irmp_data_p->address;
command = irmp_data_p->command;
irsnd_buffer[0] = 0x4A;
irsnd_buffer[1] = 0x75;
irsnd_buffer[2] = 0xC3;
irsnd_buffer[3] = 0x64;
irsnd_buffer[4] = 0x9B;
irsnd_buffer[5] = ~(address & 0xFF00) >> 8;
irsnd_buffer[6] = (address & 0xFF00) >> 8;
irsnd_buffer[7] = ~(address & 0x00FF);
irsnd_buffer[8] = (address & 0x00FF);
irsnd_buffer[9] = ~(command & 0x00FF);
irsnd_buffer[10] = (command & 0x00FF);
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
case IRMP_RECS80_PROTOCOL:
{
toggle_bit_recs80 = toggle_bit_recs80 ? 0x00 : 0x80;
irsnd_buffer[0] = toggle_bit_recs80 | ((irmp_data_p->address & 0x000F) << 4) |
((irmp_data_p->command & 0x003C) >> 2); // TAAACCCC
irsnd_buffer[1] = (irmp_data_p->command & 0x03) << 6; // CC000000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
case IRMP_RECS80EXT_PROTOCOL:
{
toggle_bit_recs80ext = toggle_bit_recs80ext ? 0x00 : 0x40;
irsnd_buffer[0] = 0x80 | toggle_bit_recs80ext | ((irmp_data_p->address & 0x000F) << 2) |
((irmp_data_p->command & 0x0030) >> 4); // STAAAACC
irsnd_buffer[1] = (irmp_data_p->command & 0x0F) << 4; // CCCC0000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
case IRMP_RC5_PROTOCOL:
{
toggle_bit_rc5 = toggle_bit_rc5 ? 0x00 : 0x40;
irsnd_buffer[0] = ((irmp_data_p->command & 0x40) ? 0x00 : 0x80) | toggle_bit_rc5 |
((irmp_data_p->address & 0x001F) << 1) | ((irmp_data_p->command & 0x20) >> 5); // CTAAAAAC
irsnd_buffer[1] = (irmp_data_p->command & 0x1F) << 3; // CCCCC000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
case IRMP_RC6_PROTOCOL:
{
toggle_bit_rc6 = toggle_bit_rc6 ? 0x00 : 0x08;
irsnd_buffer[0] = 0x80 | toggle_bit_rc6 | ((irmp_data_p->address & 0x00E0) >> 5); // 1MMMTAAA, MMM = 000
irsnd_buffer[1] = ((irmp_data_p->address & 0x001F) << 3) | ((irmp_data_p->command & 0xE0) >> 5); // AAAAACCC
irsnd_buffer[2] = (irmp_data_p->command & 0x1F) << 3; // CCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RC6A_PROTOCOL == 1
case IRMP_RC6A_PROTOCOL:
{
toggle_bit_rc6 = toggle_bit_rc6 ? 0x00 : 0x08;
irsnd_buffer[0] = 0x80 | 0x60 | ((irmp_data_p->address & 0x3000) >> 12); // 1MMMT0AA, MMM = 110
irsnd_buffer[1] = ((irmp_data_p->address & 0x0FFF) >> 4) ; // AAAAAAAA
irsnd_buffer[2] = ((irmp_data_p->address & 0x000F) << 4) | ((irmp_data_p->command & 0xF000) >> 12) | toggle_bit_rc6; // AAAACCCC
irsnd_buffer[3] = (irmp_data_p->command & 0x0FF0) >> 4; // CCCCCCCC
irsnd_buffer[4] = (irmp_data_p->command & 0x000F) << 4; // CCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
case IRMP_DENON_PROTOCOL:
{
irsnd_buffer[0] = ((irmp_data_p->address & 0x1F) << 3) | ((irmp_data_p->command & 0x0380) >> 7); // AAAAACCC (1st frame)
irsnd_buffer[1] = (irmp_data_p->command & 0x7F) << 1; // CCCCCCC
irsnd_buffer[2] = ((irmp_data_p->address & 0x1F) << 3) | (((~irmp_data_p->command) & 0x0380) >> 7); // AAAAAccc (2nd frame)
irsnd_buffer[3] = (~(irmp_data_p->command) & 0x7F) << 1; // ccccccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
case IRMP_THOMSON_PROTOCOL:
{
toggle_bit_thomson = toggle_bit_thomson ? 0x00 : 0x08;
irsnd_buffer[0] = ((irmp_data_p->address & 0x0F) << 4) | toggle_bit_thomson | ((irmp_data_p->command & 0x0070) >> 4); // AAAATCCC (1st frame)
irsnd_buffer[1] = (irmp_data_p->command & 0x0F) << 4; // CCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_BOSE_PROTOCOL == 1
case IRMP_BOSE_PROTOCOL:
{
command = bitsrevervse (irmp_data_p->command, BOSE_COMMAND_LEN);
irsnd_buffer[0] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[1] = ~((command & 0xFF00) >> 8); // cccccccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
case IRMP_NUBERT_PROTOCOL:
{
irsnd_buffer[0] = irmp_data_p->command >> 2; // CCCCCCCC
irsnd_buffer[1] = (irmp_data_p->command & 0x0003) << 6; // CC000000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_FAN_PROTOCOL == 1
case IRMP_FAN_PROTOCOL:
{
irsnd_buffer[0] = irmp_data_p->command >> 3; // CCCCCCCC
irsnd_buffer[1] = (irmp_data_p->command & 0x0007) << 5; // CCC00000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1
case IRMP_SPEAKER_PROTOCOL:
{
irsnd_buffer[0] = irmp_data_p->command >> 2; // CCCCCCCC
irsnd_buffer[1] = (irmp_data_p->command & 0x0003) << 6; // CC000000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
case IRMP_BANG_OLUFSEN_PROTOCOL:
{
irsnd_buffer[0] = irmp_data_p->command >> 11; // SXSCCCCC
irsnd_buffer[1] = irmp_data_p->command >> 3; // CCCCCCCC
irsnd_buffer[2] = (irmp_data_p->command & 0x0007) << 5; // CCC00000
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
case IRMP_GRUNDIG_PROTOCOL:
{
command = bitsrevervse (irmp_data_p->command, GRUNDIG_COMMAND_LEN);
irsnd_buffer[0] = 0xFF; // S1111111 (1st frame)
irsnd_buffer[1] = 0xC0; // 11
irsnd_buffer[2] = 0x80 | (command >> 2); // SCCCCCCC (2nd frame)
irsnd_buffer[3] = (command << 6) & 0xC0; // CC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1
case IRMP_TELEFUNKEN_PROTOCOL:
{
irsnd_buffer[0] = irmp_data_p->command >> 7; // CCCCCCCC
irsnd_buffer[1] = (irmp_data_p->command << 1) & 0xff; // CCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
case IRMP_IR60_PROTOCOL:
{
command = (bitsrevervse (0x7d, IR60_COMMAND_LEN) << 7) | bitsrevervse (irmp_data_p->command, IR60_COMMAND_LEN);
#if 1
irsnd_buffer[0] = command >> 6 | 0x01; // 1011111S (start instruction frame)
irsnd_buffer[1] = (command & 0x7F) << 1; // CCCCCCC_ (2nd frame)
#else
irsnd_buffer[0] = ((command & 0x7F) << 1) | 0x01; // CCCCCCCS (1st frame)
irsnd_buffer[1] = command >> 6; // 1011111_ (start instruction frame)
#endif
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
case IRMP_NOKIA_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, NOKIA_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, NOKIA_COMMAND_LEN);
irsnd_buffer[0] = 0xBF; // S0111111 (1st + 3rd frame)
irsnd_buffer[1] = 0xFF; // 11111111
irsnd_buffer[2] = 0x80; // 1
irsnd_buffer[3] = 0x80 | command >> 1; // SCCCCCCC (2nd frame)
irsnd_buffer[4] = (command << 7) | (address >> 1); // CAAAAAAA
irsnd_buffer[5] = (address << 7); // A
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
case IRMP_SIEMENS_PROTOCOL:
{
irsnd_buffer[0] = ((irmp_data_p->address & 0x07FF) >> 3); // AAAAAAAA
irsnd_buffer[1] = ((irmp_data_p->address & 0x0007) << 5) | ((irmp_data_p->command >> 5) & 0x1F); // AAACCCCC
irsnd_buffer[2] = ((irmp_data_p->command & 0x001F) << 3) | ((~irmp_data_p->command & 0x01) << 2); // CCCCCc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1
case IRMP_RUWIDO_PROTOCOL:
{
irsnd_buffer[0] = ((irmp_data_p->address & 0x01FF) >> 1); // AAAAAAAA
irsnd_buffer[1] = ((irmp_data_p->address & 0x0001) << 7) | ((irmp_data_p->command & 0x7F)); // ACCCCCCC
irsnd_buffer[2] = ((~irmp_data_p->command & 0x01) << 7); // c
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
case IRMP_FDC_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, FDC_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, FDC_COMMAND_LEN);
irsnd_buffer[0] = (address & 0xFF); // AAAAAAAA
irsnd_buffer[1] = 0; // 00000000
irsnd_buffer[2] = 0; // 0000RRRR
irsnd_buffer[3] = (command & 0xFF); // CCCCCCCC
irsnd_buffer[4] = ~(command & 0xFF); // cccccccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_RCCAR_PROTOCOL == 1
case IRMP_RCCAR_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, 2); // A0 A1
command = bitsrevervse (irmp_data_p->command, RCCAR_COMMAND_LEN - 2); // D0 D1 D2 D3 D4 D5 D6 D7 C0 C1 V
irsnd_buffer[0] = ((command & 0x06) << 5) | ((address & 0x0003) << 4) | ((command & 0x0780) >> 7); // C0 C1 A0 A1 D0 D1 D2 D3
irsnd_buffer[1] = ((command & 0x78) << 1) | ((command & 0x0001) << 3); // D4 D5 D6 D7 V 0 0 0
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_JVC_PROTOCOL == 1
case IRMP_JVC_PROTOCOL:
{
address = bitsrevervse (irmp_data_p->address, JVC_ADDRESS_LEN);
command = bitsrevervse (irmp_data_p->command, JVC_COMMAND_LEN);
irsnd_buffer[0] = ((address & 0x000F) << 4) | (command & 0x0F00) >> 8; // AAAACCCC
irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
case IRMP_NIKON_PROTOCOL:
{
irsnd_buffer[0] = (irmp_data_p->command & 0x0003) << 6; // CC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1
case IRMP_LEGO_PROTOCOL:
{
uint8_t crc = 0x0F ^ ((irmp_data_p->command & 0x0F00) >> 8) ^ ((irmp_data_p->command & 0x00F0) >> 4) ^ (irmp_data_p->command & 0x000F);
irsnd_buffer[0] = (irmp_data_p->command & 0x0FF0) >> 4; // CCCCCCCC
irsnd_buffer[1] = ((irmp_data_p->command & 0x000F) << 4) | crc; // CCCCcccc
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_IRMP16_PROTOCOL == 1
case IRMP_IRMP16_PROTOCOL:
{
command = bitsrevervse (irmp_data_p->command, IRMP16_COMMAND_LEN);
irsnd_buffer[0] = (command & 0xFF00) >> 8; // CCCCCCCC
irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
case IRMP_A1TVBOX_PROTOCOL:
{
irsnd_buffer[0] = 0x80 | (irmp_data_p->address >> 2); // 10AAAAAA
irsnd_buffer[1] = (irmp_data_p->address << 6) | (irmp_data_p->command >> 2); // AACCCCCC
irsnd_buffer[2] = (irmp_data_p->command << 6); // CC
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1
case IRMP_ROOMBA_PROTOCOL:
{
irsnd_buffer[0] = (irmp_data_p->command & 0x7F) << 1; // CCCCCCC.
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_PENTAX_PROTOCOL == 1
case IRMP_PENTAX_PROTOCOL:
{
irsnd_buffer[0] = (irmp_data_p->command & 0x3F) << 2; // CCCCCC..
irsnd_busy = TRUE;
break;
}
#endif
#if IRSND_SUPPORT_ACP24_PROTOCOL == 1
# define ACP_SET_BIT(acp24_bitno, c, irmp_bitno) \
do \
{ \
if ((c) & (1<<(irmp_bitno))) \
{ \
irsnd_buffer[((acp24_bitno)>>3)] |= 1 << (((7 - (acp24_bitno)) & 0x07)); \
} \
} while (0)
case IRMP_ACP24_PROTOCOL:
{
uint16_t cmd = irmp_data_p->command;
uint8_t i;
address = bitsrevervse (irmp_data_p->address, ACP24_ADDRESS_LEN);
for (i = 0; i < 8; i++)
{
irsnd_buffer[i] = 0x00; // CCCCCCCC
}
// ACP24-Frame:
// 1 2 3 4 5 6
// 0123456789012345678901234567890123456789012345678901234567890123456789
// N VVMMM ? ??? t vmA x y TTTT
//
// irmp_data_p->command:
//
// 5432109876543210
// NAVVvMMMmtxyTTTT
ACP_SET_BIT( 0, cmd, 15);
ACP_SET_BIT(24, cmd, 14);
ACP_SET_BIT( 2, cmd, 13);
ACP_SET_BIT( 3, cmd, 12);
ACP_SET_BIT(22, cmd, 11);
ACP_SET_BIT( 4, cmd, 10);
ACP_SET_BIT( 5, cmd, 9);
ACP_SET_BIT( 6, cmd, 8);
ACP_SET_BIT(23, cmd, 7);
ACP_SET_BIT(20, cmd, 6);
ACP_SET_BIT(26, cmd, 5);
ACP_SET_BIT(44, cmd, 4);
ACP_SET_BIT(66, cmd, 3);
ACP_SET_BIT(67, cmd, 2);
ACP_SET_BIT(68, cmd, 1);
ACP_SET_BIT(69, cmd, 0);
irsnd_busy = TRUE;
break;
}
#endif
// @formatter:off
default:
{
return (FALSE); // Error here: we called irsnd_send_data with a non enabled protocol!
break;
}
// @formatter:on
}
#if defined(ARDUINO)
storeIRTimer(); // store current timer state to enable alternately send and receive with the same timer
initIRTimerForSend(); // Setup timer and interrupts for sending
if (do_wait)
{
while (irsnd_busy)
{
// Wait for frame and leading space to be sent;
}
}
return true; // next frame may start immediately if do_wait was true
#else
return irsnd_busy;
#endif
}
void irsnd_stop(void)
{
irsnd_repeat = 0;
}
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ISR routine
* @details ISR routine, called from 10000 to 20000, typically 15000 times per second
* If new frame starts, check for autorepeat gap, then check for trailing space gap, then initialize frame.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
# ifdef __cplusplus
bool
#else
uint8_t
#endif
irsnd_ISR(void)
{
// @formatter:off
#if !defined(ARDUINO) // never send a trailing space for Arduino
static uint8_t send_last_trailer = FALSE; // Only for last trailer after n repeats. if TRUE, we send the trailing space as defined in repeat_frame_pause_len
#endif
static uint8_t current_bit = 0xFF; // 0xFF => send start bit
static uint8_t pulse_counter = 0;
static IRSND_PAUSE_LEN pause_counter = 0;
static uint8_t startbit_pulse_len = 0;
static IRSND_PAUSE_LEN startbit_pause_len = 0;
static uint8_t pulse_1_len = 0;
static uint8_t pause_1_len = 0;
static uint8_t pulse_0_len = 0;
static uint8_t pause_0_len = 0;
static uint8_t has_stop_bit = 0;
static uint8_t new_frame = TRUE;
static uint8_t complete_data_len = 0;
static uint8_t n_repeat_frames = 0; // number of repetition frames
static uint8_t n_auto_repetitions = 0; // number of frames inclusive auto_repetition frames
static uint8_t auto_repetition_counter = 0; // auto_repetition counter
static uint16_t auto_repetition_pause_len = 0; // pause before auto_repetition, uint16_t!
static uint16_t auto_repetition_pause_counter = 0; // pause before auto_repetition, uint16_t!
static uint8_t repeat_counter = 0; // repeat counter
static uint16_t repeat_frame_pause_len = 0; // pause before repeat, uint16_t!
static uint16_t packet_repeat_pause_counter = 0; // pause before repeat, uint16_t!
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
static uint8_t last_bit_value;
#endif
static uint8_t pulse_len = 0xFF;
static IRSND_PAUSE_LEN pause_len = 0xFF;
// @formatter:on
if (irsnd_busy)
{
if (current_bit == 0xFF && new_frame) // start of transmission...
{
// check for autorepeat gap, then check for trailing space gap, then initialize frame.
if (auto_repetition_counter > 0)
{
/*
* Send gap between auto repetitions
*/
auto_repetition_pause_counter++; // count gap duration
if (auto_repetition_pause_counter >= auto_repetition_pause_len)
{
auto_repetition_pause_counter = 0; // end of auto repetition space
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
if (irsnd_protocol == IRMP_DENON_PROTOCOL) // n'th denon frame
{
current_bit = 16;
complete_data_len = 2 * DENON_COMPLETE_DATA_LEN + 1;
}
else
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL) // n'th grundig frame
{
current_bit = 15;
complete_data_len = 16 + GRUNDIG_COMPLETE_DATA_LEN;
}
else
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
if (irsnd_protocol == IRMP_IR60_PROTOCOL) // n'th IR60 frame
{
current_bit = 7;
complete_data_len = 2 * IR60_COMPLETE_DATA_LEN + 1;
}
else
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
if (irsnd_protocol == IRMP_NOKIA_PROTOCOL) // n'th nokia frame
{
if (auto_repetition_counter + 1 < n_auto_repetitions)
{
current_bit = 23;
complete_data_len = 24 + NOKIA_COMPLETE_DATA_LEN;
}
else // nokia stop frame
{
current_bit = 0xFF;
complete_data_len = NOKIA_COMPLETE_DATA_LEN;
}
}
else
#endif
{
;
}
}
else
{
#if defined(ANALYZE)
if (irsnd_is_on)
{
putchar('0');
}
else
{
putchar('1');
}
#endif
// auto repetition pause here
return irsnd_busy;
}
}
/*
* Send trailing space
*/
else if (packet_repeat_pause_counter < repeat_frame_pause_len)
{
/*
* Send trailing space, especially for repeats
*/
packet_repeat_pause_counter++; // count trailing space duration
#if defined(ANALYZE)
if (irsnd_is_on)
{
putchar ('0');
}
else
{
putchar ('1');
}
#endif
return irsnd_busy;
}
else
{
// End of trailing space here => initialize new frame
#if !defined(ARDUINO) // never send a trailing space for Arduino
if (send_last_trailer)
{
irsnd_busy = FALSE; // Trailing space sent complete, stop sending
send_last_trailer = FALSE;
return irsnd_busy;
}
#endif
n_repeat_frames = irsnd_repeat;
if (n_repeat_frames == IRSND_ENDLESS_REPETITION)
{
n_repeat_frames = 255;
}
packet_repeat_pause_counter = 0;
pulse_counter = 0;
pause_counter = 0;
/*
* Initialize new frame for selected protocol
*/
switch (irsnd_protocol)
{
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
case IRMP_SIRCS_PROTOCOL:
{
startbit_pulse_len = IRSND_SIRCS_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_SIRCS_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_SIRCS_1_PULSE_LEN;
pause_1_len = IRSND_SIRCS_PAUSE_LEN - 1;
pulse_0_len = IRSND_SIRCS_0_PULSE_LEN;
pause_0_len = IRSND_SIRCS_PAUSE_LEN - 1;
has_stop_bit = SIRCS_STOP_BIT;
complete_data_len = SIRCS_MINIMUM_DATA_LEN + sircs_additional_bitlen;
n_auto_repetitions = (repeat_counter == 0) ? SIRCS_FRAMES : 1; // 3 frames auto repetition if first frame
auto_repetition_pause_len = IRSND_SIRCS_AUTO_REPETITION_PAUSE_LEN; // 25ms pause
repeat_frame_pause_len = IRSND_SIRCS_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_40_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
case IRMP_NEC_PROTOCOL:
case IRMP_NEC_REPETITION_PROTOCOL:
case IRMP_ONKYO_PROTOCOL:
{
startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN;
if (repeat_counter > 0 || irsnd_protocol == IRMP_NEC_REPETITION_PROTOCOL)
{
startbit_pause_len = IRSND_NEC_REPEAT_START_BIT_PAUSE_LEN - 1;
complete_data_len = 0;
}
else
{
startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1;
complete_data_len = NEC_COMPLETE_DATA_LEN;
}
pulse_1_len = IRSND_NEC_PULSE_LEN;
pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NEC_PULSE_LEN;
pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1;
has_stop_bit = NEC_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
case IRMP_NEC16_PROTOCOL:
{
startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_NEC_PULSE_LEN;
pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NEC_PULSE_LEN;
pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1;
has_stop_bit = NEC_STOP_BIT;
complete_data_len = NEC16_COMPLETE_DATA_LEN + 1; // 1 more: sync bit
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NEC42_PROTOCOL == 1
case IRMP_NEC42_PROTOCOL:
{
startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_NEC_PULSE_LEN;
pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NEC_PULSE_LEN;
pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1;
has_stop_bit = NEC_STOP_BIT;
complete_data_len = NEC42_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_MELINERA_PROTOCOL == 1
case IRMP_MELINERA_PROTOCOL:
{
startbit_pulse_len = IRSND_MELINERA_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_MELINERA_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_MELINERA_1_PULSE_LEN;
pause_1_len = IRSND_MELINERA_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_MELINERA_0_PULSE_LEN;
pause_0_len = IRSND_MELINERA_0_PAUSE_LEN - 1;
has_stop_bit = MELINERA_STOP_BIT;
complete_data_len = MELINERA_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_MELINERA_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_LGAIR_PROTOCOL == 1
case IRMP_LGAIR_PROTOCOL:
{
startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_NEC_PULSE_LEN;
pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NEC_PULSE_LEN;
pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1;
has_stop_bit = NEC_STOP_BIT;
complete_data_len = LGAIR_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
case IRMP_SAMSUNG_PROTOCOL:
{
startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_SAMSUNG_PULSE_LEN;
pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_SAMSUNG_PULSE_LEN;
pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1;
has_stop_bit = SAMSUNG_STOP_BIT;
complete_data_len = SAMSUNG_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_SAMSUNG_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
case IRMP_SAMSUNG32_PROTOCOL:
{
startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_SAMSUNG_PULSE_LEN;
pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_SAMSUNG_PULSE_LEN;
pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1;
has_stop_bit = SAMSUNG_STOP_BIT;
complete_data_len = SAMSUNG32_COMPLETE_DATA_LEN;
n_auto_repetitions = SAMSUNG32_FRAMES; // 1 frame
auto_repetition_pause_len = IRSND_SAMSUNG32_AUTO_REPETITION_PAUSE_LEN; // 47 ms pause
repeat_frame_pause_len = IRSND_SAMSUNG32_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1
case IRMP_SAMSUNG48_PROTOCOL:
{
startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_SAMSUNG_PULSE_LEN;
pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_SAMSUNG_PULSE_LEN;
pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1;
has_stop_bit = SAMSUNG_STOP_BIT;
complete_data_len = SAMSUNG48_COMPLETE_DATA_LEN;
n_auto_repetitions = SAMSUNG48_FRAMES; // 1 frame
auto_repetition_pause_len = IRSND_SAMSUNG48_AUTO_REPETITION_PAUSE_LEN; // 47 ms pause
repeat_frame_pause_len = IRSND_SAMSUNG48_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
case IRMP_MATSUSHITA_PROTOCOL:
{
startbit_pulse_len = IRSND_MATSUSHITA_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_MATSUSHITA_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_MATSUSHITA_PULSE_LEN;
pause_1_len = IRSND_MATSUSHITA_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_MATSUSHITA_PULSE_LEN;
pause_0_len = IRSND_MATSUSHITA_0_PAUSE_LEN - 1;
has_stop_bit = MATSUSHITA_STOP_BIT;
complete_data_len = MATSUSHITA_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1
case IRMP_TECHNICS_PROTOCOL:
{
startbit_pulse_len = IRSND_MATSUSHITA_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_MATSUSHITA_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_MATSUSHITA_PULSE_LEN;
pause_1_len = IRSND_MATSUSHITA_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_MATSUSHITA_PULSE_LEN;
pause_0_len = IRSND_MATSUSHITA_0_PAUSE_LEN - 1;
has_stop_bit = MATSUSHITA_STOP_BIT;
complete_data_len = TECHNICS_COMPLETE_DATA_LEN; // here TECHNICS
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1
case IRMP_KASEIKYO_PROTOCOL:
{
startbit_pulse_len = IRSND_KASEIKYO_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_KASEIKYO_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_KASEIKYO_PULSE_LEN;
pause_1_len = IRSND_KASEIKYO_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_KASEIKYO_PULSE_LEN;
pause_0_len = IRSND_KASEIKYO_0_PAUSE_LEN - 1;
has_stop_bit = KASEIKYO_STOP_BIT;
complete_data_len = KASEIKYO_COMPLETE_DATA_LEN;
n_auto_repetitions = KASEIKYO_FRAMES; // 1 frame
auto_repetition_pause_len = IRSND_KASEIKYO_AUTO_REPETITION_PAUSE_LEN; // 75 ms pause
repeat_frame_pause_len = IRSND_KASEIKYO_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1
case IRMP_PANASONIC_PROTOCOL:
{
startbit_pulse_len = IRSND_PANASONIC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_PANASONIC_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_PANASONIC_PULSE_LEN;
pause_1_len = IRSND_PANASONIC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_PANASONIC_PULSE_LEN;
pause_0_len = IRSND_PANASONIC_0_PAUSE_LEN - 1;
has_stop_bit = PANASONIC_STOP_BIT;
complete_data_len = PANASONIC_COMPLETE_DATA_LEN;
n_auto_repetitions = PANASONIC_FRAMES; // 1 frame
auto_repetition_pause_len = IRSND_PANASONIC_AUTO_REPETITION_PAUSE_LEN; // 40 ms pause
repeat_frame_pause_len = IRSND_PANASONIC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
case IRMP_MITSU_HEAVY_PROTOCOL:
{
startbit_pulse_len = IRSND_MITSU_HEAVY_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_MITSU_HEAVY_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_MITSU_HEAVY_PULSE_LEN;
pause_1_len = IRSND_MITSU_HEAVY_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_MITSU_HEAVY_PULSE_LEN;
pause_0_len = IRSND_MITSU_HEAVY_0_PAUSE_LEN - 1;
has_stop_bit = MITSU_HEAVY_STOP_BIT;
complete_data_len = MITSU_HEAVY_COMPLETE_DATA_LEN;
n_auto_repetitions = MITSU_HEAVY_FRAMES; // 1 frame
auto_repetition_pause_len = 0;;
repeat_frame_pause_len = IRSND_MITSU_HEAVY_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_40_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
case IRMP_RECS80_PROTOCOL:
{
startbit_pulse_len = IRSND_RECS80_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RECS80_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_RECS80_PULSE_LEN;
pause_1_len = IRSND_RECS80_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_RECS80_PULSE_LEN;
pause_0_len = IRSND_RECS80_0_PAUSE_LEN - 1;
has_stop_bit = RECS80_STOP_BIT;
complete_data_len = RECS80_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RECS80_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
case IRMP_RECS80EXT_PROTOCOL:
{
startbit_pulse_len = IRSND_RECS80EXT_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RECS80EXT_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_RECS80EXT_PULSE_LEN;
pause_1_len = IRSND_RECS80EXT_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_RECS80EXT_PULSE_LEN;
pause_0_len = IRSND_RECS80EXT_0_PAUSE_LEN - 1;
has_stop_bit = RECS80EXT_STOP_BIT;
complete_data_len = RECS80EXT_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RECS80EXT_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1
case IRMP_TELEFUNKEN_PROTOCOL:
{
startbit_pulse_len = IRSND_TELEFUNKEN_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_TELEFUNKEN_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_TELEFUNKEN_PULSE_LEN;
pause_1_len = IRSND_TELEFUNKEN_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_TELEFUNKEN_PULSE_LEN;
pause_0_len = IRSND_TELEFUNKEN_0_PAUSE_LEN - 1;
has_stop_bit = TELEFUNKEN_STOP_BIT;
complete_data_len = TELEFUNKEN_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frames
auto_repetition_pause_len = 0; // IRSND_TELEFUNKEN_AUTO_REPETITION_PAUSE_LEN; xx ms pause
repeat_frame_pause_len = IRSND_TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
case IRMP_RC5_PROTOCOL:
{
startbit_pulse_len = IRSND_RC5_BIT_LEN;
startbit_pause_len = IRSND_RC5_BIT_LEN;
pulse_len = IRSND_RC5_BIT_LEN;
pause_len = IRSND_RC5_BIT_LEN;
has_stop_bit = RC5_STOP_BIT;
complete_data_len = RC5_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RC5_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
case IRMP_RC6_PROTOCOL:
{
startbit_pulse_len = IRSND_RC6_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RC6_START_BIT_PAUSE_LEN - 1;
pulse_len = IRSND_RC6_BIT_LEN;
pause_len = IRSND_RC6_BIT_LEN;
has_stop_bit = RC6_STOP_BIT;
complete_data_len = RC6_COMPLETE_DATA_LEN_SHORT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RC6_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RC6A_PROTOCOL == 1
case IRMP_RC6A_PROTOCOL:
{
startbit_pulse_len = IRSND_RC6_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RC6_START_BIT_PAUSE_LEN - 1;
pulse_len = IRSND_RC6_BIT_LEN;
pause_len = IRSND_RC6_BIT_LEN;
has_stop_bit = RC6_STOP_BIT;
complete_data_len = RC6_COMPLETE_DATA_LEN_LONG;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RC6_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
case IRMP_DENON_PROTOCOL:
{
startbit_pulse_len = 0x00;
startbit_pause_len = 0x00;
pulse_1_len = IRSND_DENON_PULSE_LEN;
pause_1_len = IRSND_DENON_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_DENON_PULSE_LEN;
pause_0_len = IRSND_DENON_0_PAUSE_LEN - 1;
has_stop_bit = DENON_STOP_BIT;
complete_data_len = DENON_COMPLETE_DATA_LEN;
n_auto_repetitions = DENON_FRAMES; // 2 frames, 2nd with inverted command
auto_repetition_pause_len = IRSND_DENON_AUTO_REPETITION_PAUSE_LEN; // 65 ms pause after 1st frame
repeat_frame_pause_len = IRSND_DENON_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ); // in theory 32kHz, in practice 36kHz is better
break;
}
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
case IRMP_THOMSON_PROTOCOL:
{
startbit_pulse_len = 0x00;
startbit_pause_len = 0x00;
pulse_1_len = IRSND_THOMSON_PULSE_LEN;
pause_1_len = IRSND_THOMSON_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_THOMSON_PULSE_LEN;
pause_0_len = IRSND_THOMSON_0_PAUSE_LEN - 1;
has_stop_bit = THOMSON_STOP_BIT;
complete_data_len = THOMSON_COMPLETE_DATA_LEN;
n_auto_repetitions = THOMSON_FRAMES; // only 1 frame
auto_repetition_pause_len = IRSND_THOMSON_AUTO_REPETITION_PAUSE_LEN;
repeat_frame_pause_len = IRSND_THOMSON_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_BOSE_PROTOCOL == 1
case IRMP_BOSE_PROTOCOL:
{
startbit_pulse_len = IRSND_BOSE_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_BOSE_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_BOSE_PULSE_LEN;
pause_1_len = IRSND_BOSE_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_BOSE_PULSE_LEN;
pause_0_len = IRSND_BOSE_0_PAUSE_LEN - 1;
has_stop_bit = BOSE_STOP_BIT;
complete_data_len = BOSE_COMPLETE_DATA_LEN;
n_auto_repetitions = BOSE_FRAMES; // 1 frame
auto_repetition_pause_len = IRSND_BOSE_AUTO_REPETITION_PAUSE_LEN; // 40 ms pause
repeat_frame_pause_len = IRSND_BOSE_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
case IRMP_NUBERT_PROTOCOL:
{
startbit_pulse_len = IRSND_NUBERT_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_NUBERT_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_NUBERT_1_PULSE_LEN;
pause_1_len = IRSND_NUBERT_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NUBERT_0_PULSE_LEN;
pause_0_len = IRSND_NUBERT_0_PAUSE_LEN - 1;
has_stop_bit = NUBERT_STOP_BIT;
complete_data_len = NUBERT_COMPLETE_DATA_LEN;
n_auto_repetitions = NUBERT_FRAMES; // 2 frames
auto_repetition_pause_len = IRSND_NUBERT_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause
repeat_frame_pause_len = IRSND_NUBERT_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_FAN_PROTOCOL == 1
case IRMP_FAN_PROTOCOL:
{
startbit_pulse_len = IRSND_FAN_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_FAN_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_FAN_1_PULSE_LEN;
pause_1_len = IRSND_FAN_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_FAN_0_PULSE_LEN;
pause_0_len = IRSND_FAN_0_PAUSE_LEN - 1;
has_stop_bit = FAN_STOP_BIT;
complete_data_len = FAN_COMPLETE_DATA_LEN;
n_auto_repetitions = FAN_FRAMES; // only 1 frame
auto_repetition_pause_len = IRSND_FAN_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause
repeat_frame_pause_len = IRSND_FAN_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1
case IRMP_SPEAKER_PROTOCOL:
{
startbit_pulse_len = IRSND_SPEAKER_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_SPEAKER_START_BIT_PAUSE_LEN - 1;
pulse_1_len = IRSND_SPEAKER_1_PULSE_LEN;
pause_1_len = IRSND_SPEAKER_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_SPEAKER_0_PULSE_LEN;
pause_0_len = IRSND_SPEAKER_0_PAUSE_LEN - 1;
has_stop_bit = SPEAKER_STOP_BIT;
complete_data_len = SPEAKER_COMPLETE_DATA_LEN;
n_auto_repetitions = SPEAKER_FRAMES; // 2 frames
auto_repetition_pause_len = IRSND_SPEAKER_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause
repeat_frame_pause_len = IRSND_SPEAKER_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
case IRMP_BANG_OLUFSEN_PROTOCOL:
{
startbit_pulse_len = IRSND_BANG_OLUFSEN_START_BIT1_PULSE_LEN;
startbit_pause_len = IRSND_BANG_OLUFSEN_START_BIT1_PAUSE_LEN - 1;
pulse_1_len = IRSND_BANG_OLUFSEN_PULSE_LEN;
pause_1_len = IRSND_BANG_OLUFSEN_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_BANG_OLUFSEN_PULSE_LEN;
pause_0_len = IRSND_BANG_OLUFSEN_0_PAUSE_LEN - 1;
has_stop_bit = BANG_OLUFSEN_STOP_BIT;
complete_data_len = BANG_OLUFSEN_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN;
last_bit_value = 0;
irsnd_set_freq (IRSND_FREQ_455_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
case IRMP_GRUNDIG_PROTOCOL:
{
startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1;
pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT;
complete_data_len = GRUNDIG_COMPLETE_DATA_LEN;
n_auto_repetitions = GRUNDIG_FRAMES; // 2 frames
auto_repetition_pause_len = IRSND_GRUNDIG_AUTO_REPETITION_PAUSE_LEN; // 20m sec pause
repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
case IRMP_IR60_PROTOCOL:
{
startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1;
pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT;
complete_data_len = IR60_COMPLETE_DATA_LEN;
n_auto_repetitions = IR60_FRAMES; // 2 frames
auto_repetition_pause_len = IRSND_IR60_AUTO_REPETITION_PAUSE_LEN; // 20m sec pause
repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
irsnd_set_freq (IRSND_FREQ_30_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
case IRMP_NOKIA_PROTOCOL:
{
startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1;
pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT;
complete_data_len = NOKIA_COMPLETE_DATA_LEN;
n_auto_repetitions = NOKIA_FRAMES; // 2 frames
auto_repetition_pause_len = IRSND_NOKIA_AUTO_REPETITION_PAUSE_LEN; // 20 msec pause
repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
case IRMP_SIEMENS_PROTOCOL:
{
startbit_pulse_len = IRSND_SIEMENS_BIT_LEN;
startbit_pause_len = IRSND_SIEMENS_BIT_LEN;
pulse_len = IRSND_SIEMENS_BIT_LEN;
pause_len = IRSND_SIEMENS_BIT_LEN;
has_stop_bit = SIEMENS_OR_RUWIDO_STOP_BIT;
complete_data_len = SIEMENS_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_SIEMENS_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1
case IRMP_RUWIDO_PROTOCOL:
{
startbit_pulse_len = IRSND_RUWIDO_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RUWIDO_START_BIT_PAUSE_LEN;
pulse_len = IRSND_RUWIDO_BIT_PULSE_LEN;
pause_len = IRSND_RUWIDO_BIT_PAUSE_LEN;
has_stop_bit = SIEMENS_OR_RUWIDO_STOP_BIT;
complete_data_len = RUWIDO_COMPLETE_DATA_LEN;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RUWIDO_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_36_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
case IRMP_FDC_PROTOCOL:
{
startbit_pulse_len = IRSND_FDC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_FDC_START_BIT_PAUSE_LEN - 1;
complete_data_len = FDC_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_FDC_PULSE_LEN;
pause_1_len = IRSND_FDC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_FDC_PULSE_LEN;
pause_0_len = IRSND_FDC_0_PAUSE_LEN - 1;
has_stop_bit = FDC_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_FDC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_RCCAR_PROTOCOL == 1
case IRMP_RCCAR_PROTOCOL:
{
startbit_pulse_len = IRSND_RCCAR_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_RCCAR_START_BIT_PAUSE_LEN - 1;
complete_data_len = RCCAR_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_RCCAR_PULSE_LEN;
pause_1_len = IRSND_RCCAR_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_RCCAR_PULSE_LEN;
pause_0_len = IRSND_RCCAR_0_PAUSE_LEN - 1;
has_stop_bit = RCCAR_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_RCCAR_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_JVC_PROTOCOL == 1
case IRMP_JVC_PROTOCOL:
{
if (repeat_counter != 0) // skip start bit if repetition frame
{
current_bit = 0;
}
startbit_pulse_len = IRSND_JVC_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_JVC_START_BIT_PAUSE_LEN - 1;
complete_data_len = JVC_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_JVC_PULSE_LEN;
pause_1_len = IRSND_JVC_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_JVC_PULSE_LEN;
pause_0_len = IRSND_JVC_0_PAUSE_LEN - 1;
has_stop_bit = JVC_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_JVC_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
case IRMP_NIKON_PROTOCOL:
{
startbit_pulse_len = IRSND_NIKON_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_NIKON_START_BIT_PAUSE_LEN;
complete_data_len = NIKON_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_NIKON_PULSE_LEN;
pause_1_len = IRSND_NIKON_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_NIKON_PULSE_LEN;
pause_0_len = IRSND_NIKON_0_PAUSE_LEN - 1;
has_stop_bit = NIKON_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_NIKON_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1
case IRMP_LEGO_PROTOCOL:
{
startbit_pulse_len = IRSND_LEGO_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_LEGO_START_BIT_PAUSE_LEN - 1;
complete_data_len = LEGO_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_LEGO_PULSE_LEN;
pause_1_len = IRSND_LEGO_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_LEGO_PULSE_LEN;
pause_0_len = IRSND_LEGO_0_PAUSE_LEN - 1;
has_stop_bit = LEGO_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_LEGO_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_IRMP16_PROTOCOL == 1
case IRMP_IRMP16_PROTOCOL:
{
startbit_pulse_len = IRSND_IRMP16_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_IRMP16_START_BIT_PAUSE_LEN - 1;
complete_data_len = IRMP16_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_IRMP16_PULSE_LEN;
pause_1_len = IRSND_IRMP16_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_IRMP16_PULSE_LEN;
pause_0_len = IRSND_IRMP16_0_PAUSE_LEN - 1;
has_stop_bit = IRMP16_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_IRMP16_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
case IRMP_A1TVBOX_PROTOCOL:
{
startbit_pulse_len = IRSND_A1TVBOX_BIT_PULSE_LEN; // don't use A1TVBOX_START_BIT_PULSE_LEN
startbit_pause_len = IRSND_A1TVBOX_BIT_PAUSE_LEN; // don't use A1TVBOX_START_BIT_PAUSE_LEN
pulse_len = IRSND_A1TVBOX_BIT_PULSE_LEN;
pause_len = IRSND_A1TVBOX_BIT_PAUSE_LEN;
has_stop_bit = A1TVBOX_STOP_BIT;
complete_data_len = A1TVBOX_COMPLETE_DATA_LEN + 1; // we send stop bit as data
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1
case IRMP_ROOMBA_PROTOCOL:
{
startbit_pulse_len = IRSND_ROOMBA_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_ROOMBA_START_BIT_PAUSE_LEN;
pulse_1_len = IRSND_ROOMBA_1_PULSE_LEN;
pause_1_len = IRSND_ROOMBA_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_ROOMBA_0_PULSE_LEN;
pause_0_len = IRSND_ROOMBA_0_PAUSE_LEN - 1;
has_stop_bit = ROOMBA_STOP_BIT;
complete_data_len = ROOMBA_COMPLETE_DATA_LEN;
n_auto_repetitions = ROOMBA_FRAMES; // 8 frames
auto_repetition_pause_len = IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN;
repeat_frame_pause_len = IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_PENTAX_PROTOCOL == 1
case IRMP_PENTAX_PROTOCOL:
{
startbit_pulse_len = IRSND_PENTAX_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_PENTAX_START_BIT_PAUSE_LEN;
complete_data_len = PENTAX_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_PENTAX_PULSE_LEN;
pause_1_len = IRSND_PENTAX_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_PENTAX_PULSE_LEN;
pause_0_len = IRSND_PENTAX_0_PAUSE_LEN - 1;
has_stop_bit = PENTAX_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_PENTAX_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
#if IRSND_SUPPORT_ACP24_PROTOCOL == 1
case IRMP_ACP24_PROTOCOL:
{
startbit_pulse_len = IRSND_ACP24_START_BIT_PULSE_LEN;
startbit_pause_len = IRSND_ACP24_START_BIT_PAUSE_LEN - 1;
complete_data_len = ACP24_COMPLETE_DATA_LEN;
pulse_1_len = IRSND_ACP24_PULSE_LEN;
pause_1_len = IRSND_ACP24_1_PAUSE_LEN - 1;
pulse_0_len = IRSND_ACP24_PULSE_LEN;
pause_0_len = IRSND_ACP24_0_PAUSE_LEN - 1;
has_stop_bit = ACP24_STOP_BIT;
n_auto_repetitions = 1; // 1 frame
auto_repetition_pause_len = 0;
repeat_frame_pause_len = IRSND_ACP24_FRAME_REPEAT_PAUSE_LEN;
irsnd_set_freq (IRSND_FREQ_38_KHZ);
break;
}
#endif
// @formatter:off
default:
{
irsnd_busy = FALSE; // no enabled protocol is selected -> stop immediately
break;
}
// @formatter:on
}
}
} // if (current_bit == 0xFF && new_frame)
if (irsnd_busy)
{
new_frame = FALSE; // we just have sent start bit here
switch (irsnd_protocol)
{
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
case IRMP_SIRCS_PROTOCOL:
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
case IRMP_NEC_PROTOCOL:
case IRMP_NEC_REPETITION_PROTOCOL:
case IRMP_ONKYO_PROTOCOL:
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
case IRMP_NEC16_PROTOCOL:
#endif
#if IRSND_SUPPORT_NEC42_PROTOCOL == 1
case IRMP_NEC42_PROTOCOL:
#endif
#if IRSND_SUPPORT_LGAIR_PROTOCOL == 1
case IRMP_LGAIR_PROTOCOL:
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
case IRMP_SAMSUNG_PROTOCOL:
case IRMP_SAMSUNG32_PROTOCOL:
#endif
#if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1
case IRMP_SAMSUNG48_PROTOCOL:
#endif
#if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
case IRMP_MATSUSHITA_PROTOCOL:
#endif
#if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1
case IRMP_TECHNICS_PROTOCOL:
#endif
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1
case IRMP_KASEIKYO_PROTOCOL:
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
case IRMP_RECS80_PROTOCOL:
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
case IRMP_RECS80EXT_PROTOCOL:
#endif
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
case IRMP_DENON_PROTOCOL:
#endif
#if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
case IRMP_NUBERT_PROTOCOL:
#endif
#if IRSND_SUPPORT_FAN_PROTOCOL == 1
case IRMP_FAN_PROTOCOL:
#endif
#if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1
case IRMP_SPEAKER_PROTOCOL:
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
case IRMP_BANG_OLUFSEN_PROTOCOL:
#endif
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
case IRMP_FDC_PROTOCOL:
#endif
#if IRSND_SUPPORT_RCCAR_PROTOCOL == 1
case IRMP_RCCAR_PROTOCOL:
#endif
#if IRSND_SUPPORT_JVC_PROTOCOL == 1
case IRMP_JVC_PROTOCOL:
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
case IRMP_NIKON_PROTOCOL:
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1
case IRMP_LEGO_PROTOCOL:
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
case IRMP_THOMSON_PROTOCOL:
#endif
#if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1
case IRMP_ROOMBA_PROTOCOL:
#endif
#if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1
case IRMP_TELEFUNKEN_PROTOCOL:
#endif
#if IRSND_SUPPORT_PENTAX_PROTOCOL == 1
case IRMP_PENTAX_PROTOCOL:
#endif
#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1
case IRMP_PANASONIC_PROTOCOL:
#endif
#if IRSND_SUPPORT_ACP24_PROTOCOL == 1
case IRMP_ACP24_PROTOCOL:
#endif
#if IRSND_SUPPORT_BOSE_PROTOCOL == 1
case IRMP_BOSE_PROTOCOL:
#endif
#if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
case IRMP_MITSU_HEAVY_PROTOCOL:
#endif
#if IRSND_SUPPORT_IRMP16_PROTOCOL == 1
case IRMP_IRMP16_PROTOCOL:
#endif
#if IRSND_SUPPORT_MELINERA_PROTOCOL == 1
case IRMP_MELINERA_PROTOCOL:
#endif
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 || IRSND_SUPPORT_NEC_PROTOCOL == 1 || IRSND_SUPPORT_NEC16_PROTOCOL == 1 || IRSND_SUPPORT_NEC42_PROTOCOL == 1 || \
IRSND_SUPPORT_LGAIR_PROTOCOL == 1 || IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 || IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 || IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 || \
IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 || IRSND_SUPPORT_RECS80_PROTOCOL == 1 || IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 || IRSND_SUPPORT_DENON_PROTOCOL == 1 || \
IRSND_SUPPORT_NUBERT_PROTOCOL == 1 || IRSND_SUPPORT_FAN_PROTOCOL == 1 || IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 || IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 || \
IRSND_SUPPORT_FDC_PROTOCOL == 1 || IRSND_SUPPORT_RCCAR_PROTOCOL == 1 || IRSND_SUPPORT_JVC_PROTOCOL == 1 || IRSND_SUPPORT_NIKON_PROTOCOL == 1 || \
IRSND_SUPPORT_LEGO_PROTOCOL == 1 || IRSND_SUPPORT_THOMSON_PROTOCOL == 1 || IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 || IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 || \
IRSND_SUPPORT_PENTAX_PROTOCOL == 1 || IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 || IRSND_SUPPORT_ACP24_PROTOCOL == 1 || IRSND_SUPPORT_BOSE_PROTOCOL == 1 || \
IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 || IRSND_SUPPORT_IRMP16_PROTOCOL == 1 || IRSND_SUPPORT_MELINERA_PROTOCOL // guard for content of case
{
if (pulse_counter == 0)
{
if (current_bit == 0xFF) // send start bit
{
pulse_len = startbit_pulse_len;
pause_len = startbit_pause_len;
}
else if (current_bit < complete_data_len) // send n'th bit
{
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
if (irsnd_protocol == IRMP_SAMSUNG_PROTOCOL)
{
if (current_bit < SAMSUNG_ADDRESS_LEN) // send address bits
{
pulse_len = IRSND_SAMSUNG_PULSE_LEN;
pause_len = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ?
(IRSND_SAMSUNG_1_PAUSE_LEN - 1) : (IRSND_SAMSUNG_0_PAUSE_LEN - 1);
}
else if (current_bit == SAMSUNG_ADDRESS_LEN) // send SYNC bit (16th bit)
{
pulse_len = IRSND_SAMSUNG_PULSE_LEN;
pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1;
}
else if (current_bit < SAMSUNG_COMPLETE_DATA_LEN) // send n'th bit
{
uint8_t cur_bit = current_bit - 1; // sync skipped, offset = -1 !
pulse_len = IRSND_SAMSUNG_PULSE_LEN;
pause_len = (irsnd_buffer[cur_bit >> 3] & (1<<(7-(cur_bit & 7)))) ?
(IRSND_SAMSUNG_1_PAUSE_LEN - 1) : (IRSND_SAMSUNG_0_PAUSE_LEN - 1);
}
}
else
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
if (irsnd_protocol == IRMP_NEC16_PROTOCOL)
{
if (current_bit < NEC16_ADDRESS_LEN) // send address bits
{
pulse_len = IRSND_NEC_PULSE_LEN;
pause_len = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ?
(IRSND_NEC_1_PAUSE_LEN - 1) : (IRSND_NEC_0_PAUSE_LEN - 1);
}
else if (current_bit == NEC16_ADDRESS_LEN) // send SYNC bit (8th bit)
{
pulse_len = IRSND_NEC_PULSE_LEN;
pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1;
}
else if (current_bit < NEC16_COMPLETE_DATA_LEN + 1) // send n'th bit
{
uint8_t cur_bit = current_bit - 1; // sync skipped, offset = -1 !
pulse_len = IRSND_NEC_PULSE_LEN;
pause_len = (irsnd_buffer[cur_bit >> 3] & (1<<(7-(cur_bit & 7)))) ?
(IRSND_NEC_1_PAUSE_LEN - 1) : (IRSND_NEC_0_PAUSE_LEN - 1);
}
}
else
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
if (irsnd_protocol == IRMP_BANG_OLUFSEN_PROTOCOL)
{
if (current_bit == 0) // send 2nd start bit
{
pulse_len = IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN;
pause_len = IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN - 1;
}
else if (current_bit == 1) // send 3rd start bit
{
pulse_len = IRSND_BANG_OLUFSEN_START_BIT3_PULSE_LEN;
pause_len = IRSND_BANG_OLUFSEN_START_BIT3_PAUSE_LEN - 1;
}
else if (current_bit == 2) // send 4th start bit
{
pulse_len = IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN;
pause_len = IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN - 1;
}
else if (current_bit == 19) // send trailer bit
{
pulse_len = IRSND_BANG_OLUFSEN_PULSE_LEN;
pause_len = IRSND_BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN - 1;
}
else if (current_bit < BANG_OLUFSEN_COMPLETE_DATA_LEN) // send n'th bit
{
uint8_t cur_bit_value = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? 1 : 0;
pulse_len = IRSND_BANG_OLUFSEN_PULSE_LEN;
if (cur_bit_value == last_bit_value)
{
pause_len = IRSND_BANG_OLUFSEN_R_PAUSE_LEN - 1;
}
else
{
pause_len = cur_bit_value ? (IRSND_BANG_OLUFSEN_1_PAUSE_LEN - 1) : (IRSND_BANG_OLUFSEN_0_PAUSE_LEN - 1);
last_bit_value = cur_bit_value;
}
}
}
else
#endif
if (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7))))
{
pulse_len = pulse_1_len;
pause_len = pause_1_len;
}
else
{
pulse_len = pulse_0_len;
pause_len = pause_0_len;
}
}
else if (has_stop_bit) // send stop bit
{
pulse_len = pulse_0_len;
if (auto_repetition_counter < n_auto_repetitions)
{
pause_len = pause_0_len;
}
else
{
pause_len = 255; // last frame: pause of 255
}
}
}
if (pulse_counter < pulse_len)
{
if (pulse_counter == 0)
{
irsnd_on ();
}
pulse_counter++;
}
else if (pause_counter < pause_len)
{
if (pause_counter == 0)
{
irsnd_off ();
}
pause_counter++;
}
else
{
current_bit++;
if (current_bit >= complete_data_len + has_stop_bit)
{
/*
* End of current frame, prepare for a new frame
*/
current_bit = 0xFF;
new_frame = TRUE;
auto_repetition_counter++;
if (auto_repetition_counter == n_auto_repetitions)
{
irsnd_busy = FALSE;
auto_repetition_counter = 0;
}
}
pulse_counter = 0;
pause_counter = 0;
}
break;
}
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
case IRMP_RC5_PROTOCOL:
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
case IRMP_RC6_PROTOCOL:
#endif
#if IRSND_SUPPORT_RC6A_PROTOCOL == 1
case IRMP_RC6A_PROTOCOL:
#endif
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
case IRMP_SIEMENS_PROTOCOL:
#endif
#if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1
case IRMP_RUWIDO_PROTOCOL:
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
case IRMP_GRUNDIG_PROTOCOL:
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
case IRMP_IR60_PROTOCOL:
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
case IRMP_NOKIA_PROTOCOL:
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
case IRMP_A1TVBOX_PROTOCOL:
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1 || \
IRSND_SUPPORT_RC6_PROTOCOL == 1 || \
IRSND_SUPPORT_RC6A_PROTOCOL == 1 || \
IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 || \
IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 || \
IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || \
IRSND_SUPPORT_IR60_PROTOCOL == 1 || \
IRSND_SUPPORT_NOKIA_PROTOCOL == 1 || \
IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 // guard for content of case
{
if (pulse_counter == pulse_len && pause_counter == pause_len)
{
current_bit++;
if (current_bit >= complete_data_len)
{
current_bit = 0xFF;
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_IR60_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL)
{
auto_repetition_counter++;
if (repeat_counter > 0)
{ // set 117 msec pause time
auto_repetition_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN;
}
if (repeat_counter < n_repeat_frames) // tricky: repeat n info frames per auto repetition before sending last stop frame
{
n_auto_repetitions++; // increment number of auto repetitions
repeat_counter++;
}
else if (auto_repetition_counter == n_auto_repetitions)
{
irsnd_busy = FALSE;
auto_repetition_counter = 0;
}
}
else
#endif
{
irsnd_busy = FALSE;
}
new_frame = TRUE;
irsnd_off ();
}
pulse_counter = 0;
pause_counter = 0;
}
if (! new_frame)
{
uint8_t first_pulse;
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_IR60_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL)
{
if (current_bit == 0xFF || // start bit of start-frame
(irsnd_protocol == IRMP_GRUNDIG_PROTOCOL && current_bit == 15) || // start bit of info-frame (Grundig)
(irsnd_protocol == IRMP_IR60_PROTOCOL && current_bit == 7) || // start bit of data frame (IR60)
(irsnd_protocol == IRMP_NOKIA_PROTOCOL && (current_bit == 23 || current_bit == 47))) // start bit of info- or stop-frame (Nokia)
{
pulse_len = startbit_pulse_len;
pause_len = startbit_pause_len;
first_pulse = TRUE;
}
else // send n'th bit
{
pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN;
first_pulse = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? TRUE : FALSE;
}
}
else // if (irsnd_protocol == IRMP_RC5_PROTOCOL || irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL ||
// irsnd_protocol == IRMP_SIEMENS_PROTOCOL || irsnd_protocol == IRMP_RUWIDO_PROTOCOL)
#endif
{
if (current_bit == 0xFF) // 1 start bit
{
#if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1
if (irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL)
{
pulse_len = startbit_pulse_len;
pause_len = startbit_pause_len;
}
else
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
if (irsnd_protocol == IRMP_A1TVBOX_PROTOCOL)
{
current_bit = 0;
}
else
#endif
{
;
}
first_pulse = TRUE;
}
else // send n'th bit
{
#if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1
if (irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL)
{
pulse_len = IRSND_RC6_BIT_LEN;
pause_len = IRSND_RC6_BIT_LEN;
if (irsnd_protocol == IRMP_RC6_PROTOCOL)
{
if (current_bit == 4) // toggle bit (double len)
{
pulse_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC_BIT_LEN
pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC_BIT_LEN
}
}
else // if (irsnd_protocol == IRMP_RC6A_PROTOCOL)
{
if (current_bit == 4) // toggle bit (double len)
{
pulse_len = IRSND_RC6_BIT_3_LEN; // = 3 * RC6_BIT_LEN
pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC6_BIT_LEN
}
else if (current_bit == 5) // toggle bit (double len)
{
pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC6_BIT_LEN
}
}
}
#endif
first_pulse = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? TRUE : FALSE;
}
if (irsnd_protocol == IRMP_RC5_PROTOCOL)
{
first_pulse = first_pulse ? FALSE : TRUE;
}
}
if (first_pulse)
{
// printf ("first_pulse: current_bit: %d %d < %d %d < %d\n", current_bit, pause_counter, pause_len, pulse_counter, pulse_len);
if (pulse_counter < pulse_len)
{
if (pulse_counter == 0)
{
irsnd_on ();
}
pulse_counter++;
}
else // if (pause_counter < pause_len)
{
if (pause_counter == 0)
{
irsnd_off ();
}
pause_counter++;
}
}
else
{
// printf ("first_pause: current_bit: %d %d < %d %d < %d\n", current_bit, pause_counter, pause_len, pulse_counter, pulse_len);
if (pause_counter < pause_len)
{
if (pause_counter == 0)
{
irsnd_off ();
}
pause_counter++;
}
else // if (pulse_counter < pulse_len)
{
if (pulse_counter == 0)
{
irsnd_on ();
}
pulse_counter++;
}
}
}
break;
}
#endif // IRSND_SUPPORT_RC5_PROTOCOL == 1 || IRSND_SUPPORT_RC6_PROTOCOL == 1 || || IRSND_SUPPORT_RC6A_PROTOCOL == 1 || IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 ||
// IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 || IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1
// @formatter:off
default:
{
// Just in case ...
irsnd_busy = FALSE;
break;
}
// @formatter:on
}
}
if (!irsnd_busy)
{
/*
* Check if we are really finished or if we must send a repeat or a trailing space
*/
if (repeat_counter < n_repeat_frames)
{
// repeat again
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
if (irsnd_protocol == IRMP_FDC_PROTOCOL)
{
irsnd_buffer[2] |= 0x0F;
}
#endif
repeat_counter++;
irsnd_busy = TRUE;
}
else
{
#if !defined(ARDUINO) // never send a trailing space for Arduino
if (!irsnd_suppress_trailer)
{
/*
* Switch to mode: send last trailing space
*/
irsnd_busy = TRUE;
send_last_trailer = TRUE;
}
#endif
// cleanup for ending transmission
n_repeat_frames = 0;
repeat_counter = 0;
repeat_frame_pause_len = 0;
}
}
}
#if defined(ANALYZE)
if (irsnd_is_on)
{
putchar ('0');
}
else
{
putchar ('1');
}
#endif
return irsnd_busy;
}
#if defined(ANALYZE)
// main function - for unix/linux + windows only!
// AVR: see main.c!
// Compile it under linux with:
// cc irsnd.c -o irsnd
//
// usage: ./irsnd protocol hex-address hex-command >filename
int
main (int argc, char ** argv)
{
int protocol;
int address;
int command;
IRMP_DATA irmp_data;
if (argc != 4 && argc != 5)
{
fprintf (stderr, "usage: %s protocol hex-address hex-command [repeat] > filename\n", argv[0]);
return 1;
}
if (sscanf (argv[1], "%d", &protocol) == 1 &&
sscanf (argv[2], "%x", &address) == 1 &&
sscanf (argv[3], "%x", &command) == 1)
{
irmp_data.protocol = protocol;
irmp_data.address = address;
irmp_data.command = command;
if (argc == 5)
{
irmp_data.flags = atoi (argv[4]);
}
else
{
irmp_data.flags = 0;
}
irsnd_init ();
(void) irsnd_send_data (&irmp_data, TRUE);
while (irsnd_busy)
{
irsnd_ISR ();
}
putchar ('\n');
#if 0 // enable here to send twice
(void) irsnd_send_data (&irmp_data, TRUE);
while (irsnd_busy)
{
irsnd_ISR ();
}
putchar ('\n');
#endif
}
else
{
fprintf (stderr, "%s: wrong arguments\n", argv[0]);
return 1;
}
return 0;
}
#endif // ANALYZE
================================================
FILE: src/irsndArduinoExt.h
================================================
/*
* irsndArduinoExt.h Arduino extensions to the original irsnd.h
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#if defined(ARDUINO)
#ifndef _IRSND_ARDUINO_EXT_H
#define _IRSND_ARDUINO_EXT_H
#include "irmpVersion.h"
#include "digitalWriteFast.h" // we use pinModeFast() and digitalReadFast() and digitalWriteFast() in turn
#if defined(IR_OUTPUT_IS_ACTIVE_LOW) || defined(IRSND_GENERATE_NO_SEND_RF)
#define IR_OUTPUT_ACTIVE_LEVEL LOW
#define IR_OUTPUT_INACTIVE_LEVEL HIGH
#else
#define IR_OUTPUT_ACTIVE_LEVEL HIGH
#define IR_OUTPUT_INACTIVE_LEVEL LOW
#endif
//
/*
* Set hardware pin defaults for Arduino IDE if no IRSND_OUTPUT_PIN specified
*/
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
extern uint_fast8_t irsnd_output_pin;
#undef IRSND_OUTPUT_PIN
#define IRSND_OUTPUT_PIN irsnd_output_pin
void irsnd_init(uint_fast8_t aIrsndOutputPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);
#else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
# if !defined(IRSND_OUTPUT_PIN) // Arduino IDE uses IRSND_OUTPUT_PIN instead of PORT and BIT
#define IRSND_OUTPUT_PIN 4
# endif
#endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
void irsnd_data_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr);
#if defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3
#include "mbed.h"
#define F_CPU 0 // dummy definition to avoid warning at irsnd.hpp:27 #error F_CPU unkown
#endif
#if !defined(IR_TIMING_TEST_PIN) // Only for test purposes
#define IR_TIMING_TEST_PIN 5
#endif
#if ! defined(IRSND_IR_FREQUENCY)
#define IRSND_IR_FREQUENCY 38000
#endif
#define IRSND_INTERRUPT_FREQUENCY (IRSND_IR_FREQUENCY * 2) // *2 to toggle output pin at each interrupt
/*
* For Arduino AVR use timer 2 with FIXED 38000 * 2 = 76000 interrupts per second to toggle output pin.
* ISR is called each 4. interrupt at a rate of 19000 interrupts per second.
* (Re)define F_INTERRUPTS to the resulting call value in order to generate correct values for all the protocols.
*/
# undef F_INTERRUPTS
# define F_INTERRUPTS (IRSND_IR_FREQUENCY / 2) // 19000 interrupts per second
extern volatile uint8_t irsnd_is_on; // Used by IRTimer.hpp
extern volatile uint8_t irsnd_busy; // Used by IRTimer.hpp
#endif /* _IRSND_ARDUINO_EXT_H */
#endif // ARDUINO
================================================
FILE: src/irsndArduinoExt.hpp
================================================
/*
* irsndArduinoExt.hpp - Arduino extensions to the original irsnd.c
*
* Copyright (C) 2020 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
*
* IRMP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#if defined(ARDUINO)
#undef _IRMP_H_ // We are in IRSND now! Remove old symbol set from former including irmp.hpp if we use receive and send in the same user program.
#include "IRTimer.hpp" // include code for timer
#include "IRFeedbackLED.hpp" // include code for Feedback LED
#include "irmpprotocols.hpp" // include protocol strings and array of strings
#if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
uint_fast8_t irsnd_output_pin;
/*
* Initialize, and activate feedback LED function
* @param aFeedbackLedPin - if 0 feedback function is disabled
*/
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow)
{
irsnd_output_pin = aIrsndOutputPin;
#if !defined(NO_LED_FEEDBACK_CODE)
irmp_irsnd_LedFeedbackPin = aFeedbackLedPin;
irmp_irsnd_LedFeedbackPinIsActiveLow = aIrmpLedFeedbackPinIsActiveLow;
/*
* enable feedback LED if (aFeedbackLedPin != 0)
*/
irmp_irsnd_LEDFeedback(aFeedbackLedPin);
#else
(void) aFeedbackLedPin; // to avoid compiler warnings
(void) aIrmpLedFeedbackPinIsActiveLow; // to avoid compiler warnings
#endif
// Do not call irsnd_init_and_store_timer() here, it is done at irsnd_send_data().
pinMode(irsnd_output_pin, OUTPUT);
# if defined(IRMP_MEASURE_TIMING)
pinModeFast(IR_TIMING_TEST_PIN, OUTPUT);
# endif
}
/*
* Initialize, and activate feedback LED function
* @param aFeedbackLedPin - if 0 feedback function is disabled
*/
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin)
{
#if defined(NO_LED_FEEDBACK_CODE)
irsnd_init(aIrsndOutputPin, aFeedbackLedPin, false);
#else
irsnd_init(aIrsndOutputPin, aFeedbackLedPin, irmp_irsnd_LedFeedbackPinIsActiveLow);
#endif
}
/*
* Initialize, use feedback LED by using 0 as led pin
*/
void irsnd_init(uint_fast8_t aIrsndOutputPin)
{
#if defined(NO_LED_FEEDBACK_CODE)
irsnd_init(aIrsndOutputPin, 0, false);
#else
irsnd_init(aIrsndOutputPin, irmp_irsnd_LedFeedbackPin, irmp_irsnd_LedFeedbackPinIsActiveLow);
#endif
# if defined(IRMP_FEEDBACK_LED_PIN)
// set pin if we have one at hand
irmp_irsnd_LedFeedbackPin = IRMP_FEEDBACK_LED_PIN;
# endif
}
#else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
/*
* Init function for defined pins
*/
void irsnd_init(void)
{
// Do not call irsnd_init_and_store_timer() here, it is done at irsnd_send_data().
pinModeFast(IRSND_OUTPUT_PIN, OUTPUT);
# if defined(IRMP_MEASURE_TIMING)
pinModeFast(IR_TIMING_TEST_PIN, OUTPUT);
# endif
}
#endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
static void irsnd_set_freq(IRSND_FREQ_TYPE freq __attribute__((unused)))
{
// not supported by now
}
/*
* Called from irsnd_ISR to set the IR output
*/
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR irsnd_on(void)
#else
void irsnd_on(void)
#endif
{
if (!irsnd_is_on)
{
#if !defined(NO_LED_FEEDBACK_CODE)
if (irmp_irsnd_LedFeedbackEnabled)
{
# if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
irmp_irsnd_SetFeedbackLED(true);
# else
# if defined(IRMP_FEEDBACK_LED_PIN)
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
// If the built in LED on the board is active LOW
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW);
# else
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH);
# endif
# endif
# endif
}
#endif
irsnd_is_on = TRUE; // evaluated at ISR
}
}
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR irsnd_off(void)
#else
void irsnd_off(void)
#endif
{
if (irsnd_is_on)
{
#if !defined(NO_LED_FEEDBACK_CODE)
// Manage feedback LED
if (irmp_irsnd_LedFeedbackEnabled)
{
# if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS)
irmp_irsnd_SetFeedbackLED(false);
# else
# if defined(IRMP_FEEDBACK_LED_PIN)
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
// If the built in LED on the board is active LOW
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH);
# else
digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW);
# endif
# endif
# endif
}
#endif
irsnd_is_on = FALSE; // evaluated at ISR
}
}
/*
* irsnd_used_protocol_index holds the protocol numbers (from irsndprotocols.h)
* for the included protocol name entries of the irsnd_used_protocol_names array below
* E.g. irmp_used_protocol_index=2,7 and irmp_used_protocol_names="NEC","RC5".
*
* Both arrays together are generally smaller than the complete irmp_protocol_names array
* allowing them to be used on ATtinies even if program code for access is bigger.
* Flash size is more than 100 bytes less (for 15 protocols) using these arrays.
*/
const uint8_t irsnd_used_protocol_index[] PROGMEM =
{
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
IRMP_SIRCS_PROTOCOL,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
IRMP_NEC_PROTOCOL,
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
IRMP_SAMSUNG_PROTOCOL,
#endif
#if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
IRMP_MATSUSHITA_PROTOCOL,
#endif
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1
IRMP_KASEIKYO_PROTOCOL,
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
IRMP_RECS80_PROTOCOL,
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
IRMP_RC5_PROTOCOL,
#endif
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
IRMP_DENON_PROTOCOL,
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
IRMP_RC6_PROTOCOL,
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
IRMP_SAMSUNG32_PROTOCOL,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
IRMP_APPLE_PROTOCOL,
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
IRMP_RECS80EXT_PROTOCOL,
#endif
#if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
IRMP_NUBERT_PROTOCOL,
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
IRMP_BANG_OLUFSEN_PROTOCOL,
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
IRMP_GRUNDIG_PROTOCOL,
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
IRMP_NOKIA_PROTOCOL,
#endif
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
IRMP_SIEMENS_PROTOCOL,
#endif
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
IRMP_FDC_PROTOCOL,
#endif
#if IRSND_SUPPORT_RCCAR_PROTOCOL == 1
IRMP_RCCAR_PROTOCOL,
#endif
#if IRSND_SUPPORT_JVC_PROTOCOL == 1
IRMP_JVC_PROTOCOL,
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
IRMP_RC6A_PROTOCOL,
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
IRMP_NIKON_PROTOCOL,
#endif
#if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1
IRMP_RUWIDO_PROTOCOL,
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
IRMP_IR60_PROTOCOL,
#endif
#if IRSND_SUPPORT_KATHREIN_PROTOCOL == 1
IRMP_KATHREIN_PROTOCOL,
#endif
#if IRSND_SUPPORT_NETBOX_PROTOCOL == 1
IRMP_NETBOX_PROTOCOL,
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
IRMP_NEC16_PROTOCOL,
#endif
#if IRSND_SUPPORT_NEC42_PROTOCOL == 1
IRMP_NEC42_PROTOCOL,
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1
IRMP_LEGO_PROTOCOL,
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
IRMP_THOMSON_PROTOCOL,
#endif
#if IRSND_SUPPORT_BOSE_PROTOCOL == 1
IRMP_BOSE_PROTOCOL,
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
IRMP_A1TVBOX_PROTOCOL,
#endif
#if IRSND_SUPPORT_ORTEK_PROTOCOL == 1
IRMP_ORTEK_PROTOCOL,
#endif
#if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1
IRMP_TELEFUNKEN_PROTOCOL,
#endif
#if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1
IRMP_ROOMBA_PROTOCOL,
#endif
#if IRSND_SUPPORT_RCMM_PROTOCOL == 1
IRMP_RCMM12_PROTOCOL,
#endif
#if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1
IRMP_SPEAKER_PROTOCOL,
#endif
#if IRSND_SUPPORT_LGAIR_PROTOCOL == 1
IRMP_LGAIR_PROTOCOL,
#endif
#if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1
IRMP_SAMSUNG48_PROTOCOL,
#endif
#if IRSND_SUPPORT_MERLIN_PROTOCOL == 1
IRMP_MERLIN_PROTOCOL,
#endif
#if IRSND_SUPPORT_PENTAX_PROTOCOL == 1
IRMP_PENTAX_PROTOCOL,
#endif
#if IRSND_SUPPORT_FAN_PROTOCOL == 1
IRMP_FAN_PROTOCOL,
#endif
#if IRSND_SUPPORT_S100_PROTOCOL == 1
IRMP_S100_PROTOCOL,
#endif
#if IRSND_SUPPORT_ACP24_PROTOCOL == 1
IRMP_ACP24_PROTOCOL,
#endif
#if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1
IRMP_TECHNICS_PROTOCOL,
#endif
#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1
IRMP_PANASONIC_PROTOCOL,
#endif
#if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
IRMP_MITSU_HEAVY_PROTOCOL,
#endif
#if IRSND_SUPPORT_VINCENT_PROTOCOL == 1
IRMP_VINCENT_PROTOCOL,
#endif
#if IRSND_SUPPORT_SAMSUNGAH_PROTOCOL == 1
IRMP_SAMSUNGAH_PROTOCOL,
#endif
#if IRSND_SUPPORT_IRMP16_PROTOCOL == 1
IRMP_IRMP16_PROTOCOL,
#endif
#if IRSND_SUPPORT_GREE_PROTOCOL == 1
IRMP_GREE_PROTOCOL,
#endif
#if IRSND_SUPPORT_RCII_PROTOCOL == 1
IRMP_RCII_PROTOCOL,
#endif
#if IRSND_SUPPORT_METZ_PROTOCOL == 1
IRMP_METZ_PROTOCOL,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
IRMP_ONKYO_PROTOCOL,
#endif
#if IRSND_SUPPORT_RF_GEN24_PROTOCOL == 1
RF_GEN24_PROTOCOL,
#endif
#if IRMP_SUPPORT_RF_X10_PROTOCOL == 1
RF_X10_PROTOCOL,
#endif
#if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1
RF_MEDION_PROTOCOL
#endif
#if IRSND_SUPPORT_MELINERA_PROTOCOL == 1
IRMP_MELINERA_PROTOCOL
#endif
};
const char * const irsnd_used_protocol_names[] PROGMEM =
{
#if IRSND_SUPPORT_SIRCS_PROTOCOL == 1
proto_sircs,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
proto_nec,
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
proto_samsung,
#endif
#if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1
proto_matsushita,
#endif
#if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1
proto_kaseikyo,
#endif
#if IRSND_SUPPORT_RECS80_PROTOCOL == 1
proto_recs80,
#endif
#if IRSND_SUPPORT_RC5_PROTOCOL == 1
proto_rc5,
#endif
#if IRSND_SUPPORT_DENON_PROTOCOL == 1
proto_denon,
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
proto_rc6,
#endif
#if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1
proto_samsung32,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
proto_apple,
#endif
#if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1
proto_recs80ext,
#endif
#if IRSND_SUPPORT_NUBERT_PROTOCOL == 1
proto_nubert,
#endif
#if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1
proto_bang_olufsen,
#endif
#if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1
proto_grundig,
#endif
#if IRSND_SUPPORT_NOKIA_PROTOCOL == 1
proto_nokia,
#endif
#if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1
proto_siemens,
#endif
#if IRSND_SUPPORT_FDC_PROTOCOL == 1
proto_fdc,
#endif
#if IRSND_SUPPORT_RCCAR_PROTOCOL == 1
proto_rccar,
#endif
#if IRSND_SUPPORT_JVC_PROTOCOL == 1
proto_jvc,
#endif
#if IRSND_SUPPORT_RC6_PROTOCOL == 1
proto_rc6a,
#endif
#if IRSND_SUPPORT_NIKON_PROTOCOL == 1
proto_nikon,
#endif
#if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1
proto_ruwido,
#endif
#if IRSND_SUPPORT_IR60_PROTOCOL == 1
proto_ir60,
#endif
#if IRSND_SUPPORT_KATHREIN_PROTOCOL == 1
proto_kathrein,
#endif
#if IRSND_SUPPORT_NETBOX_PROTOCOL == 1
proto_netbox,
#endif
#if IRSND_SUPPORT_NEC16_PROTOCOL == 1
proto_nec16,
#endif
#if IRSND_SUPPORT_NEC42_PROTOCOL == 1
proto_nec42,
#endif
#if IRSND_SUPPORT_LEGO_PROTOCOL == 1
proto_lego,
#endif
#if IRSND_SUPPORT_THOMSON_PROTOCOL == 1
proto_thomson,
#endif
#if IRSND_SUPPORT_BOSE_PROTOCOL == 1
proto_bose,
#endif
#if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1
proto_a1tvbox,
#endif
#if IRSND_SUPPORT_ORTEK_PROTOCOL == 1
proto_ortek,
#endif
#if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1
proto_telefunken,
#endif
#if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1
proto_roomba,
#endif
#if IRSND_SUPPORT_RCMM_PROTOCOL == 1
proto_rcmm12,
#endif
#if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1
proto_speaker,
#endif
#if IRSND_SUPPORT_LGAIR_PROTOCOL == 1
proto_lgair,
#endif
#if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1
proto_samsung48,
#endif
#if IRSND_SUPPORT_MERLIN_PROTOCOL == 1
proto_merlin,
#endif
#if IRSND_SUPPORT_PENTAX_PROTOCOL == 1
proto_pentax,
#endif
#if IRSND_SUPPORT_FAN_PROTOCOL == 1
proto_fan,
#endif
#if IRSND_SUPPORT_S100_PROTOCOL == 1
proto_s100,
#endif
#if IRSND_SUPPORT_ACP24_PROTOCOL == 1
proto_acp24,
#endif
#if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1
proto_technics,
#endif
#if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1
proto_panasonic,
#endif
#if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1
proto_mitsu_heavy,
#endif
#if IRSND_SUPPORT_VINCENT_PROTOCOL == 1
proto_vincent,
#endif
#if IRSND_SUPPORT_SAMSUNGAH_PROTOCOL == 1
proto_samsungah,
#endif
#if IRSND_SUPPORT_IRMP16_PROTOCOL == 1
proto_irmp16,
#endif
#if IRSND_SUPPORT_GREE_PROTOCOL == 1
proto_gree,
#endif
#if IRSND_SUPPORT_RCII_PROTOCOL == 1
proto_rcii,
#endif
#if IRSND_SUPPORT_METZ_PROTOCOL == 1
proto_metz,
#endif
#if IRSND_SUPPORT_NEC_PROTOCOL == 1
proto_onkyo,
#endif
#if IRSND_SUPPORT_RF_GEN24_PROTOCOL == 1
proto_rf_gen24,
#endif
#if IRSND_SUPPORT_RF_X10_PROTOCOL == 1
proto_rf_x10,
#endif
#if IRSND_SUPPORT_RF_MEDION_PROTOCOL == 1
proto_rf_medion
#endif
#if IRSND_SUPPORT_MELINERA_PROTOCOL == 1
proto_melinera
#endif
};
void irsnd_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber)
{
# if defined(__AVR__)
for (uint_fast8_t i = 0; i < sizeof(irsnd_used_protocol_index); ++i)
{
if (pgm_read_byte(&irsnd_used_protocol_index[i]) == aProtocolNumber)
{
const char* tProtocolStringPtr = (char*) pgm_read_word(&irsnd_used_protocol_names[i]);
aSerial->print((__FlashStringHelper *) (tProtocolStringPtr));
break;
}
}
# else
// no need to save space
aSerial->print(irmp_protocol_names[aProtocolNumber]);
# endif
}
void irsnd_data_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr)
{
/*
* Print protocol name or number
*/
aSerial->print(F("Protocol="));
#if IRSND_PROTOCOL_NAMES == 1
irsnd_print_protocol_name(aSerial, aIRMPDataPtr->protocol);
aSerial->print(' ');
#else
aSerial->print(F("0x"));
aSerial->print(aIRMPDataPtr->protocol, HEX);
#endif
/*
* Print address, code and repetition flag
*/
aSerial->print(F(" Address=0x"));
aSerial->print(aIRMPDataPtr->address, HEX);
aSerial->print(F(" Command=0x"));
aSerial->print(aIRMPDataPtr->command, HEX);
if (aIRMPDataPtr->flags & IRSND_REPETITION_MASK)
{
aSerial->print(F(" Repeats="));
aSerial->print(aIRMPDataPtr->flags & IRSND_REPETITION_MASK);
}
aSerial->println();
}
#endif // defined(ARDUINO)
================================================
FILE: src/irsndSelectAllProtocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irsndSelectAllProtocols.h
* 39 protocols supported
*
*
* Copyright (c) 2010-2019 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRSND_SELECT_PROTOCOLS_H
#define _IRSND_SELECT_PROTOCOLS_H
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more encoders.
* This saves program memory.
* 1 enable encoder
* 0 disable encoder
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes
#define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes
#define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes
// more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~150 bytes
#define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes
#define IRSND_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~200 bytes
#define IRSND_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~150 bytes
#define IRSND_SUPPORT_RC6_PROTOCOL 1 // RC6 >= 10000 ~250 bytes
#define IRSND_SUPPORT_RC6A_PROTOCOL 1 // RC6A >= 10000 ~250 bytes
#define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes
#define IRSND_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens, Gigaset >= 15000 ~150 bytes
#define IRSND_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~400 bytes
// exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~250 bytes // IR frequency 30 kHz
#define IRSND_SUPPORT_BOSE_PROTOCOL 1 // BOSE >= 10000 ~100 bytes
#define IRSND_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_NUBERT_PROTOCOL 1 // NUBERT >= 10000 ~100 bytes
#define IRSND_SUPPORT_FAN_PROTOCOL 1 // FAN (ventilator) >= 10000 ~100 bytes
#define IRSND_SUPPORT_SPEAKER_PROTOCOL 1 // SPEAKER >= 10000 ~100 bytes
#define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang&Olufsen >= 10000 ~250 bytes // IR frequency 455 kHz
#define IRSND_SUPPORT_RECS80_PROTOCOL 1 // RECS80 >= 15000 ~100 bytes
#define IRSND_SUPPORT_RECS80EXT_PROTOCOL 1 // RECS80EXT >= 15000 ~100 bytes
#define IRSND_SUPPORT_THOMSON_PROTOCOL 1 // Thomson >= 10000 ~250 bytes
#define IRSND_SUPPORT_NIKON_PROTOCOL 1 // NIKON >= 10000 ~150 bytes
#define IRSND_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 1 // Telefunken 1560 >= 10000 ~150 bytes
#define IRSND_SUPPORT_FDC_PROTOCOL 1 // FDC IR keyboard >= 10000 (better 15000) ~150 bytes
#define IRSND_SUPPORT_RCCAR_PROTOCOL 1 // RC CAR >= 10000 (better 15000) ~150 bytes
#define IRSND_SUPPORT_ROOMBA_PROTOCOL 1 // iRobot Roomba >= 10000 ~150 bytes
#define IRSND_SUPPORT_RUWIDO_PROTOCOL 1 // RUWIDO, T-Home >= 15000 ~250 bytes
#define IRSND_SUPPORT_A1TVBOX_PROTOCOL 1 // A1 TV BOX >= 15000 (better 20000) ~200 bytes
#define IRSND_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes
#define IRSND_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_LGAIR_PROTOCOL 1 // LG Air Condition >= 10000 ~150 bytes.
#define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 1 // Samsung48 >= 10000 ~100 bytes
#define IRSND_SUPPORT_PENTAX_PROTOCOL 1 // Pentax >= 10000 ~150 bytes
#define IRSND_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ACP24_PROTOCOL 1 // ACP24 >= 10000 ~150 bytes
#define IRSND_SUPPORT_TECHNICS_PROTOCOL 1 // TECHNICS >= 10000 ~200 bytes
#define IRSND_SUPPORT_PANASONIC_PROTOCOL 1 // PANASONIC Beamer >= 10000 ~150 bytes
#define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 1 // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer
#define IRSND_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Protocols Part 2: RF decoders
* If you use an IR sensor, deactivate all RF protocols!
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes
#define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes
#endif // _IRSND_SELECT_PROTOCOLS_H
================================================
FILE: src/irsndSelectMain15Protocols.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irsndSelectMain15Protocols.h
*
*
* Copyright (c) 2010-2019 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRSND_SELECT_PROTOCOLS_H
#define _IRSND_SELECT_PROTOCOLS_H
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more encoders.
* This saves program memory.
* 1 enable decoder
* 0 disable decoder
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes
#define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes
#define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes
// more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~150 bytes
#define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes
#define IRSND_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~200 bytes
#define IRSND_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~150 bytes
#define IRSND_SUPPORT_RC6_PROTOCOL 1 // RC6 >= 10000 ~250 bytes
#define IRSND_SUPPORT_RC6A_PROTOCOL 1 // RC6A >= 10000 ~250 bytes
#define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes
#define IRSND_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens, Gigaset >= 15000 ~150 bytes
#define IRSND_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~400 bytes
#endif // _IRSND_SELECT_PROTOCOLS_H
================================================
FILE: src/irsndconfig.h
================================================
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* irsndconfig.h
*
* DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRSND.H!
*
* Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#ifndef _IRSNDCONFIG_H_
#define _IRSNDCONFIG_H_
#if !defined(_IRSND_H_)
# error please include only irsnd.h, not irsndconfig.h
#endif
// #define IRSND_DEBUG 1 // activate debugging
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* F_INTERRUPTS: number of interrupts per second, should be in the range from 10000 to 20000, typically 15000
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(F_INTERRUPTS)
# define F_INTERRUPTS 15000 // interrupts per second
#endif
#if ! defined(ARDUINO)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Change settings from 1 to 0 if you want to disable one or more encoders.
* This saves program memory.
* 1 enable encoder
* 0 disable encoder
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
// typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes
#define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes
#define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes
#define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes
#define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes
// more protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_DENON_PROTOCOL 0 // DENON, Sharp >= 10000 ~200 bytes
#define IRSND_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~150 bytes
#define IRSND_SUPPORT_RC6_PROTOCOL 0 // RC6 >= 10000 ~250 bytes
#define IRSND_SUPPORT_RC6A_PROTOCOL 0 // RC6A >= 10000 ~250 bytes
#define IRSND_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~150 bytes
#define IRSND_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~150 bytes
#define IRSND_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~250 bytes
#define IRSND_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes
#define IRSND_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens, Gigaset >= 15000 ~150 bytes
#define IRSND_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~400 bytes
// exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory
#define IRSND_SUPPORT_BOSE_PROTOCOL 0 // BOSE >= 10000 ~100 bytes
#define IRSND_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~100 bytes
#define IRSND_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~100 bytes
#define IRSND_SUPPORT_SPEAKER_PROTOCOL 0 // SPEAKER >= 10000 ~100 bytes
#define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang&Olufsen >= 10000 ~250 bytes
#define IRSND_SUPPORT_RECS80_PROTOCOL 0 // RECS80 >= 15000 ~100 bytes
#define IRSND_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT >= 15000 ~100 bytes
#define IRSND_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes
#define IRSND_SUPPORT_NIKON_PROTOCOL 0 // NIKON >= 10000 ~150 bytes
#define IRSND_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 0 // Telefunken 1560 >= 10000 ~150 bytes
#define IRSND_SUPPORT_FDC_PROTOCOL 0 // FDC IR keyboard >= 10000 (better 15000) ~150 bytes
#define IRSND_SUPPORT_RCCAR_PROTOCOL 0 // RC CAR >= 10000 (better 15000) ~150 bytes
#define IRSND_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes
#define IRSND_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~250 bytes
#define IRSND_SUPPORT_A1TVBOX_PROTOCOL 0 // A1 TV BOX >= 15000 (better 20000) ~200 bytes
#define IRSND_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes
#define IRSND_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_LGAIR_PROTOCOL 0 // LG Air Condition >= 10000 ~150 bytes.
#define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 0 // Samsung48 >= 10000 ~100 bytes
#define IRSND_SUPPORT_PENTAX_PROTOCOL 0 // Pentax >= 10000 ~150 bytes
#define IRSND_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 DON'T CHANGE, NOT SUPPORTED YET!
#define IRSND_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~150 bytes
#define IRSND_SUPPORT_TECHNICS_PROTOCOL 0 // TECHNICS >= 10000 ~200 bytes
#define IRSND_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~150 bytes
#define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer
#define IRSND_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes
#endif // ! defined(ARDUINO)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* AVR XMega section:
*
* Change hardware pin here: IRSND_XMEGA_OC0A = OC0A on ATxmegas supporting OC0A, e.g. ATxmega128A1U
* IRSND_XMEGA_OC0B = OC0B on ATxmegas supporting OC0B, e.g. ATxmega128A1U
* IRSND_XMEGA_OC0C = OC0C on ATxmegas supporting OC0C, e.g. ATxmega128A1U
* IRSND_XMEGA_OC0D = OC0D on ATxmegas supporting OC0D, e.g. ATxmega128A1U
* IRSND_XMEGA_OC1A = OC1A on ATxmegas supporting OC1A, e.g. ATxmega128A1U
* IRSND_XMEGA_OC1B = OC1B on ATxmegas supporting OC1B, e.g. ATxmega128A1U
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if defined(__AVR_XMEGA__) // XMEGA
# define IRSND_PORT_PRE PORTD
# define XMEGA_Timer TCD0
# define IRSND_OCx IRSND_XMEGA_OC0B // use OC0B
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* AVR ATmega/ATTiny section:
*
* Change hardware pin here: IRSND_OC2 = OC2 on ATmegas supporting OC2, e.g. ATmega8
* IRSND_OC2A = OC2A on ATmegas supporting OC2A, e.g. ATmega88
* IRSND_OC2B = OC2B on ATmegas supporting OC2B, e.g. ATmega88
* IRSND_OC0 = OC0 on ATmegas supporting OC0, e.g. ATmega162
* IRSND_OC0A = OC0A on ATmegas/ATtinys supporting OC0A, e.g. ATtiny84, ATtiny85, ATtiny87/167
* IRSND_OC0B = OC0B on ATmegas/ATtinys supporting OC0B, e.g. ATtiny84, ATtiny85
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(ATMEL_AVR)
# define IRSND_OCx IRSND_OC2B // use OC2B
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* PIC C18 or XC8 section:
*
* Change hardware pin here: IRSND_PIC_CCP1 = RC2 on PIC 18F2550/18F4550, ...
* IRSND_PIC_CCP2 = RC1 on PIC 18F2550/18F4550, ...
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined(PIC_C18) // C18 or XC8 compiler
# if defined(__12F1840) // XC8 compiler
# define Pre_Scaler 1 // define prescaler for timer2 e.g. 1,4,16
# define F_CPU 32000000UL // PIC frequency: set your freq here
# define PIC_Scaler 2 // PIC needs /2 extra in IRSND_FREQ_32_KHZ calculation for right value
# else // C18 compiler
# define IRSND_OCx IRSND_PIC_CCP2 // Use PWMx for PIC
// change other PIC C18 specific settings:
# define F_CPU 48000000UL // PIC frequency: set your freq here
# define Pre_Scaler 4 // define prescaler for timer2 e.g. 1,4,16
# define PIC_Scaler 2 // PIC needs /2 extra in IRSND_FREQ_32_KHZ calculation for right value
# endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ARM STM32 section:
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (ARM_STM32) // use B6 as IR output on STM32
# define IRSND_PORT_LETTER B
# define IRSND_BIT_NUMBER 6
# define IRSND_TIMER_NUMBER 4
# define IRSND_TIMER_CHANNEL_NUMBER 1 // only channel 1 can be used at the moment, others won't work
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ARM STM32 with HAL section - don't change here, define IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin in STM32Cube (Main.h)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (ARM_STM32_HAL) // IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin must be defined in STM32Cube
# define IRSND_PORT_LETTER IRSND_Transmit_GPIO_Port//Port of Transmit PWM Pin e.g.
# define IRSND_BIT_NUMBER IRSND_Transmit_Pin //Pim of Transmit PWM Pin e.g.
# define IRSND_TIMER_HANDLER htim2 //Handler of Timer e.g. htim (see tim.h)
# define IRSND_TIMER_CHANNEL_NUMBER TIM_CHANNEL_2 //Channel of the used Timer PWM Pin e.g. TIM_CHANNEL_2
# define IRSND_TIMER_SPEED_APBX 64000000 //Speed of the corresponding APBx. (see STM32CubeMX: Clock Configuration)
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Teensy 3.x with teensyduino gcc compiler
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (TEENSY_ARM_CORTEX_M4)
# define IRSND_PIN 5 // choose an arduino pin with PWM function!
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* ESP8266 (Arduino, see IRSEND.ino)
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif defined (__xtensa__)
# define IRSND_PIN 0 // choose an arduino pin with PWM function!
#elif defined(ARDUINO)
// specified here to avoid else case
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Other target systems
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#elif !defined (UNIX_OR_WINDOWS)
# error target system not defined.
#endif
/*---------------------------------------------------------------------------------------------------------------------------------------------------
* Use Callbacks to indicate output signal or something else
*---------------------------------------------------------------------------------------------------------------------------------------------------
*/
#if !defined(IRSND_USE_CALLBACK)
# define IRSND_USE_CALLBACK 0 // flag: 0 = don't use callbacks, 1 = use callbacks, default is 0
#endif
#endif // _IRSNDCONFIG_H_