Compare commits

...

37 Commits

Author SHA1 Message Date
Armin f5a3af340b Documentation 2024-05-30 00:52:07 +02:00
Paliak f6e0255838
Fix callback code disable macro causing compilation error (#1231)
* FIX: callback code disable macro causing compilation error
2024-05-26 23:22:46 +02:00
Armin e0ffb2ca08 Documentation 2024-05-26 23:11:15 +02:00
Armin 60a3710597 Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) and sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent. 2024-05-24 16:29:42 +02:00
Armin a28b94fabe Added macro USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN 2024-05-15 22:11:57 +02:00
Armin 8e75076a67 Documentation + improved Samsung + improved IRremoteExtensionTest example 2024-05-14 08:55:53 +02:00
Armin d781c17620 Documentation 2024-04-24 15:08:41 +02:00
Armin b962db8f4e Bumped version to 4.3.1. Fixed overflow bug for rawlen > 254. Removed deprecated sendPulseDistance... functions with parameter aSendStopBit. 2024-03-16 01:21:05 +01:00
Armin 59f4ce4a7f Fixed bug #1214 8 bit overflow for variable containing rawlen. 2024-03-15 22:35:35 +01:00
Armin 02c0e24da9 Documentation 2024-03-15 20:54:05 +01:00
Armin c6c7f17f58 Documentation 2024-03-10 02:11:32 +01:00
Armin 672d5cb532 Changed RECORD_GAP_MICROS default value from 5000 to 8000 2024-03-08 09:21:13 +01:00
Armin 8558db8b74 ESP32-C3 modifications 2024-03-01 10:43:54 +01:00
Armin 29564e83e1 Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). 2024-02-27 11:14:16 +01:00
Armin f2838859e0 Added Hob2Hood protocol 2024-02-25 23:29:22 +01:00
Armin 3930c4148a Fixed sendSamsung() / sendSamsungLG() bug
Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd()
Added rawlen and initialGap to IRData
Bumped version to 4.3.0
2024-02-23 19:56:53 +01:00
Armin ef69840a5f Improved printIRSendUsage() 2024-02-15 18:50:02 +01:00
Armin 2c2be06431 Bumped TinyIR version to 2.1.0 2024-02-15 13:37:36 +01:00
Buzzerb 483aaa2cc3
Add ExtendedNEC support to TinyIRSender and move NEC2 to arguments (#1202)
* Add ExtendedNEC support to TinyIRSender and move NEC2 from flag to argument

Added ExtendedNEC support to TinyIRSender. Also redesigned TinyIRSender's handling of sending NEC2 repeats from a compile time flag to an argument in the send functions for NEC variants, as per discussion #1201. Modified the example script TinySender to support these changes/additions and fix a bug. Finally updated/made consistent some comments across various files and the README.

Updated TinySender.ino to send using (almost*) all protocols simultaneously to demonstrate usage of TinyIRSender, as suggested in #1202 . Users can delete or comment out unneeded protocols. *(Not all combinations of NEC2 are demonstrated for brevity).
2024-02-15 13:00:20 +01:00
Armin 7c7ced8ecb Closes #1199 2024-02-14 10:58:29 +01:00
Armin 8b9e036889 Convenience function isIRReceiverAttachedForTinyReceiver() and 3.party 2024-02-13 15:46:48 +01:00
Buzzerb 7131adf71e
Added Extended NEC Protocol to TinyIR (#1200)
Added the option to receive Extended NEC using TinyIRReceiver with a USE_EXTENDED_NEC_PROTOCOL compile option. Tested working on an Uno R3. Functions similarly to the USE_ONKYO_PROTOCOL flag, mostly reusing its code. Documentation and example file TinyReceiver.ino updated to match.
2024-02-13 15:11:11 +01:00
Armin 11ec335b35 closes #1196 2024-01-24 17:32:29 +01:00
Armin a7bd9ea78b Bumped version to 4.2.1 2024-01-23 15:59:24 +01:00
Armin fbd3565941 Documentation 2024-01-22 22:15:08 +01:00
Armin ea28282d1c Flipper Zero 2024-01-22 17:27:16 +01:00
Armin 36403d810b TinyIR 2024-01-08 11:59:21 +01:00
Armin 1144c99122 Fixes #1194 2024-01-01 00:12:46 +01:00
Armin 1008347e33 Documentation 2023-12-04 09:53:09 +01:00
Armin f80a7df244 TinyReceiver 2.0 2023-11-02 23:39:36 +01:00
Armin 8c84e03318 Documentation 2023-10-18 20:30:29 +02:00
Armin 5a27b3ad44 Fix wrong type of tEnableLEDFeedback in IRReceive.hpp 2023-10-16 23:14:17 +02:00
Florian Meier c6aa13e443
Fix wrong type of tEnableLEDFeedback in IRSend.hpp (#1177)
tEnableLEDFeedback should not be a bool, because it's used as a bitmask
with different states (Send/Receive/...). Even though a bool should be
a byte anyways, this is apprently optimized with the current platformio
toolchain for ESP8266 and causes the feedback LED to not work correctly.
2023-10-16 23:05:09 +02:00
Armin b1941ff470 Documentation 2023-10-12 09:58:00 +02:00
Armin c5f50ea538 Examples and ESP32C3 2023-09-28 23:21:26 +02:00
Armin 480ca42b1a Documentation 2023-09-01 12:42:39 +02:00
Armin fe2010270e Documentation inspired by #1158 2023-08-14 17:46:21 +02:00
95 changed files with 3606 additions and 1689 deletions

View File

@ -18,7 +18,7 @@ body:
attributes:
label: The type of board you are using.
options:
- Arduino ATmega328* board (UNO, Nano, etc.)
- Arduino ATmega328* board (Uno, Nano, etc.)
- Arduino ATmega2560 board (Mega)
- Arduino ATmega32U4 board (Leonardo, etc.)
- Arduino ATmega4809 megaAVR board (NanoEvery)

View File

@ -1,7 +1,7 @@
# https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/.github/workflows/LibraryBuild.yml
# Github workflow script to test compile all examples of an Arduino library repository.
#
# Copyright (C) 2020 Armin Joachimsmeyer
# Copyright (C) 2020-2023 Armin Joachimsmeyer
# https://github.com/ArminJo/Github-Actions
#
# Before being able to push to my .github\workflows directories,
@ -60,15 +60,16 @@ jobs:
- arduino:mbed:nano33ble
- arduino:mbed_rp2040:pico
- rp2040:rp2040:arduino_nano_connect
- ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll
- 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
# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll
# - 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
- MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128
- SparkFun:avr:promicro
# - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935
# - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935
- esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
- esp32:esp32:featheresp32:FlashFreq=80
- esp32:esp32:esp32c3
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
- STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
- stm32duino:STM32F1:genericSTM32F103C
@ -81,11 +82,13 @@ jobs:
include:
- arduino-boards-fqbn: arduino:avr:uno
build-properties: # the flags were put in compiler.cpp.extra_flags
ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3
- arduino-boards-fqbn: arduino:avr:uno|DEBUG
build-properties: # the flags were put in compiler.cpp.extra_flags
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3
TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER
All: -DEBUG
- arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM
@ -131,7 +134,7 @@ jobs:
build-properties: # the flags were put in compiler.cpp.extra_flags
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
SimpleSender: -DSEND_PWM_BY_TIMER
TinyReceiver: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE
TinyReceiver: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE -DUSE_CALLBACK_FOR_TINY_RECEIVER
TinySender: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE
- arduino-boards-fqbn: arduino:samd:arduino_zero_native
@ -155,6 +158,9 @@ jobs:
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
SimpleSender: -DSEND_PWM_BY_TIMER
#
# RP2040
#
- arduino-boards-fqbn: arduino:mbed_rp2040:pico
build-properties: # the flags were put in compiler.cpp.extra_flags
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
@ -167,6 +173,9 @@ jobs:
SimpleSender: -DSEND_PWM_BY_TIMER
All: -DRAW_BUFFER_LENGTH=700
#
# megaTinyCore
#
# https://github.com/SpenceKonde/megaTinyCore/issues/935
# - arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal
# arduino-platform: megaTinyCore:megaavr
@ -183,27 +192,33 @@ jobs:
# build-properties: # the flags were put in compiler.cpp.extra_flags
# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100
- arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll
platform-url: http://drazzy.com/package_drazzy.com_index.json
required-libraries: ATtinySerialOut
sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
build-properties: # the flags were put in compiler.cpp.extra_flags
SimpleSender: -DSEND_PWM_BY_TIMER
#
# ATTinyCore
#
# - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll
# platform-url: http://drazzy.com/package_drazzy.com_index.json
# required-libraries: ATtinySerialOut
# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
# build-properties: # the flags were put in compiler.cpp.extra_flags
# SimpleSender: -DSEND_PWM_BY_TIMER
- arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
platform-url: http://drazzy.com/package_drazzy.com_index.json
required-libraries: ATtinySerialOut
sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
build-properties: # the flags were put in compiler.cpp.extra_flags
SimpleSender: -DSEND_PWM_BY_TIMER
# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
# platform-url: http://drazzy.com/package_drazzy.com_index.json
# required-libraries: ATtinySerialOut
# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
# build-properties: # the flags were put in compiler.cpp.extra_flags
# SimpleSender: -DSEND_PWM_BY_TIMER
- arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz
platform-url: http://drazzy.com/package_drazzy.com_index.json
required-libraries: ATtinySerialOut
sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
build-properties: # the flags were put in compiler.cpp.extra_flags
SimpleSender: -DSEND_PWM_BY_TIMER
# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz
# platform-url: http://drazzy.com/package_drazzy.com_index.json
# required-libraries: ATtinySerialOut
# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino
# build-properties: # the flags were put in compiler.cpp.extra_flags
# SimpleSender: -DSEND_PWM_BY_TIMER
#
# MegaCore
#
- arduino-boards-fqbn: MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal
platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json
arduino-platform: arduino:avr,MegaCore:avr # gcc is taken from arduino:avr
@ -212,6 +227,9 @@ jobs:
SimpleSender: -DSEND_PWM_BY_TIMER
All: -DRAW_BUFFER_LENGTH=700
#
# ESP
#
- arduino-boards-fqbn: esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
sketches-exclude: TinyReceiver
@ -221,11 +239,23 @@ jobs:
- arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80
platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024
sketches-exclude: TinyReceiver # undefined reference to `TwoWire::onReceive(void (*)(int))'
build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled!
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized
All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024
- arduino-boards-fqbn: esp32:esp32:esp32c3
platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024
sketches-exclude: TinyReceiver # undefined reference to `TwoWire::onReceive(void (*)(int))'
build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled!
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized
All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024
#
# STM
#
- arduino-boards-fqbn: STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 # ST version
platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json
sketches-exclude: TinyReceiver
@ -247,6 +277,9 @@ jobs:
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700
All: -DRAW_BUFFER_LENGTH=300
#
# Others
#
- arduino-boards-fqbn: SparkFun:avr:promicro
arduino-platform: arduino:avr,SparkFun:avr
platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here
@ -284,3 +317,4 @@ jobs:
sketch-names: ${{ matrix.sketch-names }}
sketches-exclude: ${{ matrix.sketches-exclude }}
build-properties: ${{ toJson(matrix.build-properties) }}
cli-version: 0.33.0 # to avoid errors for ATTinyCore

View File

@ -30,5 +30,6 @@ These are the active contributors of this project that you may contact if there
- [Daniel Wallner](https://github.com/danielwallner) Bang & Olufsen protocol.
- [slott](https://stackoverflow.com/users/11680056/sklott) Seeduino print(unsigned long long...) support.
- [Joe Ostrander](https://github.com/joeostrander) Added support for attiny1614.
- [Buzzerb](https://github.com/Buzzerb) Added Extended NEC protocol to TinyIR and making it more consistent.
Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed.

View File

@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = ..\Arduino-IRremote_gh-pages
OUTPUT_DIRECTORY = E:\WORKSPACE_ARDUINO\lib\Arduino-IRremote_gh-pages
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and

365
README.md
View File

@ -24,57 +24,65 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
   
[![Button Contribute](https://img.shields.io/badge/Contribute-752a61?style=for-the-badge&logoColor=white&logo=GitHub)](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributing.md)
#### If you find this program useful, please give it a star.
🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/Arduino-IRremote/Arduino-IRremote)
</div>
# Overview
- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-ir-protocols)
- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote#features)
* [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-4x)
* [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-3x)
- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version)
* [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes)
- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote#errors-with-using-the-3x-versions-for-old-tutorials)
* [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote#staying-on-2x)
- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-instead-of-cpp)
- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files)
- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes)
* [Data format](https://github.com/Arduino-IRremote/Arduino-IRremote#data-format)
* [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#ambiguous-protocols)
- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes)
* [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote#send-pin)
+ [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases)
- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote#tiny-nec-receiver-and-sender)
- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#the-fast-protocol)
- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote#faq-and-hints)
* [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc)
* [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote#does-not-workcompile-with-another-library)
* [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#multiple-ir-receiver)
* [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote#increase-strength-of-sent-output-signal)
* [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-cpu-clock-frequency)
* [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#bang--olufsen-protocol)
- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#handling-unknown-protocols)
* [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote#disclaimer)
* [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolpulse_distance)
* [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown)
* [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-deal-with-protocols-not-supported-by-irremote)
- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library)
- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote#wokwi-online-examples)
- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote#issues-and-discussions)
- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library)
+ [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#changing-include-h-files-with-arduino-ide)
+ [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#modifying-compile-options--macros-with-sloeber-ide)
- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-boards)
- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage)
* [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite)
* [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#hardware-pwm-signal-generation-for-sending)
* [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#why-do-we-use-30-duty-cycle-for-sending)
- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote#how-we-decode-signals)
- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote#nec-encoding-diagrams)
- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries)
- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote#useful-links)
# Table of content
- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols)
- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#features)
* [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-4x)
* [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-3x)
- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version)
* [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes)
- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#errors-with-using-the-3x-versions-for-old-tutorials)
* [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#staying-on-2x)
- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp)
- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files)
- [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts)
- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes)
* [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure)
* [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols)
* [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#unknown-protocol)
- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes)
* [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin)
+ [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases)
- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender)
- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol)
- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints)
* [Receiving stops after analogWrite() or tone() or after running a motor.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor)
* [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc)
* [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library)
* [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver)
* [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#increase-strength-of-sent-output-signal)
* [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency)
* [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol)
- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols)
* [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer)
* [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance)
* [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown)
* [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote)
- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library)
- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#wokwi-online-examples)
- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#issues-and-discussions)
- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library)
+ [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#changing-include-h-files-with-arduino-ide)
+ [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide)
- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-boards)
- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage)
* [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite)
* [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#hardware-pwm-signal-generation-for-sending)
* [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-do-we-use-30-duty-cycle-for-sending)
- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-we-decode-signals)
- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#nec-encoding-diagrams)
- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries)
- [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md)
- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#useful-links)
- [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md)
- [License](https://github.com/Arduino-IRremote/Arduino-IRremote#license)
- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote#copyright)
- [License](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#license)
- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#copyright)
<br/>
@ -102,19 +110,21 @@ Protocols can be switched off and on by defining macros before the line `#includ
- Allows receiving and sending of **raw timing data**.
## New features with version 4.x
- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead.
- New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols.
- Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`.
- RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before.
- Callback after receiving a command - It calls your code as soon as a message was received.
- **Callback** after receiving a command - It calls your code as soon as a message was received.
- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols.
- New FAST protocol.
- Automatic printout of the **corresponding send function** with printIRSendUsage().
#### Converting your 3.x program to the 4.x version
- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder).
- The parameter `bool hasStopBit` is not longer required and removed e.g. for function `sendPulseDistanceWidth()`.
## New features with version 3.x
- **Any pin** can be used for sending -if `SEND_PWM_BY_TIMER` is not defined- and receiving.
- **Any pin** can be used for receiving and if `SEND_PWM_BY_TIMER` is not defined also for sending.
- Feedback LED can be activated for sending / receiving.
- An 8/16 bit ****command** value as well as an 16 bit **address** and a protocol number is provided for decoding (instead of the old 32 bit value).
- Protocol values comply to **protocol standards**.<br/>
@ -126,9 +136,9 @@ Protocols can be switched off and on by defining macros before the line `#includ
- Allows for the generation of non PWM signal to just **simulate an active low receiver signal** for direct connect to existent receiving devices without using IR.
- Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.<br/>
Reduces memory footprint and decreases decoding time.
- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver), which **does not require any timer resource**.
- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**.
[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries).
[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries).
<br/>
@ -141,22 +151,23 @@ If you use an (old) Arduino core that does not use the `-flto` flag for compile,
- Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar.
- Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106)
or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().<br/>
For sending, call `IrSender.begin(ENABLE_LED_FEEDBACK);` or `IrSender.begin(DISABLE_LED_FEEDBACK);` in setup().<br/>
If IR_SEND_PIN is not defined you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);`
For sending, call `IrSender.begin();` in setup().<br/>
If IR_SEND_PIN is not defined (before the line `#include <IRremote.hpp>`) you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);`
- Old `decode(decode_results *aResults)` function is replaced by simple `decode()`. So if you have a statement `if(irrecv.decode(&results))` replace it with `if (IrReceiver.decode())`.
- The decoded result is now in in `IrReceiver.decodedIRData` and not in `results` any more, therefore replace any occurrences of `results.value` and `results.decode_type` (and similar) to
`IrReceiver.decodedIRData.decodedRawData` and `IrReceiver.decodedIRData.protocol`.
- Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L90-L101).
- Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`.
- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data for **NEC** and **JVC** were renamed to `sendNECMSB`, and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized.<br/>
For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes).
- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data were renamed to `sendNECMSB`, `sendSamsungMSB()`, `sendSonyMSB()` and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized and therfore was assumed to be never used.<br/>
For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes).
### Example
#### Old 2.x program:
```c++
#include <IRremote.h>
#define RECV_PIN 2
IRrecv irrecv(RECV_PIN);
decode_results results;
@ -181,6 +192,7 @@ void loop() {
```c++
#include <IRremote.hpp>
#define IR_RECEIVE_PIN 2
void setup()
{
@ -191,7 +203,6 @@ void setup()
void loop() {
if (IrReceiver.decode()) {
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
// USE NEW 3.x FUNCTIONS
IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data
...
@ -219,12 +230,15 @@ Example:
`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.<br/>
`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.<br/>
If you **read the first binary sequence backwards** (right to left), you get the second sequence.
You may use `bitreverseOneByte()` or `bitreverse32Bit()` for this.
Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
<br/>
# Errors with using the 4.x versions for old tutorials
If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).<br/>
Most likely your code will run and you will not miss the new features...
Most likely your code will run and you will not miss the new features.
<br/>
@ -232,16 +246,14 @@ Most likely your code will run and you will not miss the new features...
Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0)
or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.<br/>
It may be sufficient and deals flawlessly with 32 bit IR codes.<br/>
If this doesn't fit your case, be assured that 3.x is at least trying to be backwards compatible, so your old examples should still work fine.
If this doesn't fit your case, be assured that 4.x is at least trying to be backwards compatible, so your old examples should still work fine.
### Drawbacks
### Drawbacks of using 2.x
- Only the following decoders are available:<br/>
` NEC ` &nbsp; &nbsp; ` Denon ` &nbsp; &nbsp; ` Panasonic ` &nbsp; &nbsp; ` JVC ` &nbsp; &nbsp; ` LG `<br/>
` RC5 ` &nbsp; &nbsp; ` RC6 ` &nbsp; &nbsp; ` Samsung ` &nbsp; &nbsp; ` Sony `
- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`.
- The old functions `sendNEC()` and `sendJVC()` are renamed to `sendNECMSB()` and `sendJVCMSB()`.<br/>
Use them to send your **old MSB-first 32 bit IR data codes**.
- No decoding by a (constant) 8/16 bit address and an 8 bit command.
- No decoding to a more meaningfull (constant) 8/16 bit address and 8 bit command.
<br/>
@ -283,14 +295,16 @@ The following macros will definitely be overridden with default values otherwise
<br/>
# Receiving IR codes
Check for **received data** with:<br/>
`if (IrReceiver.decode()) {}`<br/>
This also decodes the received data.
# IRReceiver pinouts
![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg)
## Data format
# Receiving IR codes
In your program you check for a **completly received IR frame** with:<br/>
`if (IrReceiver.decode()) {}`<br/>
This also decodes the received data.<br/>
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`.
## decodedIRData structure
```c++
struct IRData {
decode_type_t protocol; // UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
@ -360,11 +374,20 @@ Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ON
### NEC, NEC2
On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame.
This enables an easy distinction between long presses and repeated presses and saves a bit of battery energy.
This behavior is quite unique for NEC and its derived protocols like LG.
This behavior is quite unique for NEC and its derived protocols like LG and Samsung.
So there are of course also remote control systems, which uses the NEC protocol but on a long press just repeat the first frame instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.<br/>
But of course there are also remote control systems, that uses the NEC protocol but only repeat the first frame when a long press is made instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.<br/>
But be careful, the NEC2 protocol can only be detected by the NEC library decoder **after** the first frame and if you do a long press!
### Samsung, SamsungLG
On a long press, the **SamsungLG protocol** does not repeat its frame, it sends a special short repeat frame.
## Unknown protocol
Use the **ReceiveDemo example** to print out all informations about your IR protocol.<br/>
The **ReceiveDump example** gives you more information but has bad repeat detection.
If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP), which especially supports manchester protocols much better.
<br/>
# Sending IR codes
@ -377,6 +400,8 @@ Send with: IrSender.sendLG(0x2, 0x3434, <numberOfRepeats>);
You will discover that **the address is a constant** and the commands sometimes are sensibly grouped.<br/>
If you are uncertain about the numbers of repeats to use for sending, **3** is a good starting point. If this works, you can check lower values afterwards.
If you have enabled `DECODE_DISTANCE_WIDTH`, the code printed by `printIRSendUsage()` **differs between 8 and 32 bit platforms**, so it is best to run the receiving program on the same platform as the sending program.
The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**. Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.<br/>
An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols). "D" and "S" denotes device and subdevice and "F" denotes the function.
@ -385,23 +410,34 @@ Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms
Keep in mind, that **there is no delay after the last sent mark**.
If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding.
The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)` are kept for backward compatibility to **(old)** tutorials and unsupported as well as error prone.
Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
## Send pin
Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
If `IR_SEND_PIN` is specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this macro. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library).
Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.<br/>
On **ESP32** ledc channel 0 is used for gereating the IR PWM.<br/>
If `IR_SEND_PIN` is specified (as c macro), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library).
### List of public IR code databases
http://www.harctoolbox.org/IR-resources.html
## Flipper Zero
[Flipper IRDB Database](https://github.com/Lucaslhm/Flipper-IRDB)
| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) |
|-|-|
| Samsung32 | Samsung |
| NEC | NEC |
| NECext | ONKYO |
| [\<start bit>\<VendorID:16>\<VendorID parity:4>\<Genre1:4>\<Genre2:4>\<Command:10>\<ID:2>\<Parity:8>\<stop bit>](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)<br/>and ID is MSB of address.<br/>address: 8A 02 20 00<br/>command: 56 03 00 00<br/>-> **IRremote:**<br/>Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \<start bit>\<VendorID:16>\<VendorID parity:4>\<Address:12>\<Command:8>\<Parity of VendorID parity, Address and Command:8>\<stop bit> |
<br/>
# Tiny NEC receiver and sender
For applications only requiring NEC or FAST -see below- protocol, there is a special receiver / sender included,<br/>
For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,<br/>
which has very **small code size of 500 bytes and does NOT require any timer**.
Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote#irdispatcherdemo) examples.<br/>
Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.<br/>
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`.
### TinyIRReceiver usage
@ -414,12 +450,11 @@ void setup() {
initPCIInterruptForTinyReceiver(); // Enables the interrupt generation on change of IR input signal
}
void loop() {}
// This is the function, which is called if a complete command was received
// It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here
void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) {
printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags);
void loop() {
if (TinyIRReceiverData.justWritten) {
TinyIRReceiverData.justWritten = false;
printTinyReceiverResultMinimal(&Serial);
}
}
```
@ -428,7 +463,7 @@ void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags
#include "TinyIRSender.hpp"
void setup() {
sendNECMinimal(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats.
sendNEC(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats.
}
void loop() {}
@ -476,6 +511,11 @@ void loop() {}
The FAST protocol can be received by IRremote and TinyIRReceiver.
# FAQ and hints
## Receiving stops after analogWrite() or tone() or after running a motor.
The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). On some boards where a software timer is available, the software timer is used.<br/>
Be aware that the hardware timer used for receiving should not be used for `analogWrite()`.<br/>
Especially **motor** control often uses the `analogWrite()` function and will therefore stop the receiving if used on the pins indicated [here](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).<br/>
On the Uno and other AVR boards the receiver timer ist the same as the tone timer. Thus receiving will stop after a `tone()` command. See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/b962db8f4e47408df01474a57f313f5a6bbe39a1/examples/ReceiveDemo/ReceiveDemo.ino#L257) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`.
## Problems with Neopixels, FastLed etc.
IRremote will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 &micro;s).<br/>
@ -489,7 +529,7 @@ There are some other solutions to this on more powerful processors,
## Does not work/compile with another library
**Another library is only working/compiling** if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.<br/>
This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage).
This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
## Multiple IR receivers
IRreceiver consists of one timer triggered function reading the digital IR signal value from one pin every 50 &micro;s.<br/>
@ -571,7 +611,8 @@ If you do not know which protocol your IR transmitter uses, you have several cho
# Examples for this library
The examples are available at File > Examples > Examples from Custom Libraries / IRremote.<br/>
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.
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.<br/>
See also [DroneBot Workshop SimpleReceiver](https://dronebotworkshop.com/ir-remotes/#SimpleReceiver_Example_Code) and [SimpleSender](https://dronebotworkshop.com/ir-remotes/#SimpleSender_Example_Code).
#### SimpleReceiver + SimpleSender
The **[SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** and **[SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)** examples are a good starting point.
@ -579,11 +620,13 @@ A simple example can be tested online with [WOKWI](https://wokwi.com/projects/33
#### TinyReceiver + TinySender
If **code size** or **timer usage** matters, look at these examples.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.<br/>
The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library
which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**.
They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.<br/>
TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.<br/>
It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example.
It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example. It has options to send using Extended NEC, ONKYO and FAST protocols.
Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible).
#### SmallReceiver
@ -634,6 +677,9 @@ The file *acLG.h* contains the command documentation of the LG air conditioner I
IReceiverTimingAnalysis can be tested online with [WOKWI](https://wokwi.com/projects/299033930562011656)
Click on the receiver while simulation is running to specify individual IR codes.
#### ReceiveAndSendHob2Hood
[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/ReceiveAndSendHobToHood.ino) for receiving and sending AEG / Elektrolux Hob2Hood protocol.<br/>
#### ReceiverTimingAnalysis
This [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino) analyzes the signal delivered by your IR receiver module.
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.<br/>
@ -643,6 +689,8 @@ Click on the receiver while simulation is running to specify individual NEC IR c
#### UnitTest
ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**.
Here you see the delay of the receiver output (blue) from the IR diode input (yellow).
![Delay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_UnitTest_delay.bmp)
# WOKWI online examples
- [Simple receiver](https://wokwi.com/projects/338611596994544210)
@ -656,7 +704,7 @@ ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**.
# Issues and discussions
- Do not open an issue without first testing some of the examples!
- If you have a problem, please post the MCVE (Minimal Complete Verifiable Example) showing this problem. My experience is, that most of the times you will find the problem while creating this MCVE :smile:.
- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us help you when we can read your code!**
- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us to help you when we can read your code!**
<br/>
@ -666,42 +714,47 @@ These macros must be defined in your program **before** the line `#include <IRre
Modify them by enabling / disabling them, or change the values if applicable.
| Name | Default value | Description |
|:---|---:|----|
| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. |
| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. |
| `DECODE_<Protocol name>` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) |
| `DECODE_STRICT_CHECKS` | disabled | Check for additional characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. |
|-|-:|-|
| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. |
| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. |
| `DECODE_<Protocol name>` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) |
| `DECODE_STRICT_CHECKS` | disabled | Check for additional required characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. |
| `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. |
| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. |
| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.<br/>Must be greater than any space of a protocol e.g. the NEC header space of 4500 &micro;s.<br/>Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.<br/>Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. |
| `IR_SEND_PIN` | disabled | If specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. |
| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). |
| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! |
| `DISABLE_CODE_FOR_RECEIVER` | disabled | Saves up to 450 bytes program memory and 269 bytes RAM if receiving functionality is not required. |
| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. |
| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. |
| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 &micro;s at 38 kHz. |
| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. |
| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.<br/>Must be greater than any space of a protocol e.g. the NEC header space of 4500 &micro;s.<br/>Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.<br/>Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. |
| `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. |
| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). |
| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! |
| `USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN` | disabled | Only if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. |
| `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. |
| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. |
| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. |
| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 &micro;s at 38 kHz. |
| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` | 25 | Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. |
| `DEBUG` | disabled | Enables lots of lovely debug output. |
| `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. |
These next macros for **TinyIRReceiver** must be defined in your program before the line `#include <TinyIRReceiver.hpp>` to take effect.
| Name | Default value | Description |
|:---|---:|----|
|-|-:|-|
| `IR_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 | Disables the feedback LED function. Saves 14 bytes program memory. |
| `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. |
| `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. |
| `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. |
| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. |
The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include <IRCommandDispatcher.hpp>` to take effect.
| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. |
| `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. |
| `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. |
### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.<br/>
@ -721,9 +774,13 @@ If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easi
# Supported Boards
**Issues and discussions with the content "Is it possible to use this library with the ATTinyXYZ? / board XYZ" without any reasonable explanations will be immediately closed without further notice.**<br/>
For **ESP8266/ESP32**, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)<br/>
<br/>
ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board.
Digispark boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the Digispark Pro board.<br/>
ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore).
- Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc.
- Arduino Uno R4, but not yet tested, because of lack of a R4 board. **Sending does not work** on the `arduino:renesas_uno:unor4wifi`.
- Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 3.2 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team)
- Sanguino
- ATmega8, 48, 88, 168, 328
@ -734,13 +791,13 @@ ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](ht
- ATtiny84, 85, 167 (Digispark + Digispark Pro)
- SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**)
- ESP8266
- ESP32 (ESP32 C3 since board package 2.0.2 from Espressif)
- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) **not for ESP32 core version > 3.0.0**
- Sparkfun Pro Micro
- Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE
- BluePill with STM32
- RP2040 based boards (Raspberry Pi Pico, Nano RP2040 Connect etc.)
For ESP8266/ESP32, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)
We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side.<br/>
If you can provide **examples of using a periodic timer for interrupts** for the new board, and the board name for selection in the Arduino IDE, then you have way better chances to get your board supported by IRremote.
@ -749,44 +806,50 @@ If you can provide **examples of using a periodic timer for interrupts** for the
# Timer and pin usage
The **receiver sample interval of 50 &micro;s is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used.<br/>
Every pin can be used for receiving.
On **ESP8266** `timer1` is used for receive interrupts, which makes it incompatible to the Servo and other libraries.<br/>
On **ESP32** `hw_timer_t` is used for receive interrupts and `ledc` channel 0 is used for generating the IR PWM.
Every pin can be used for receiving.<br/>
If software PWM is selected, which is default, every pin can also be used for sending. Sending with software PWM does not require a timer!
The TinyReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer** and runs even on a 1 MHz ATtiny85.
The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). It can be adjusted here.<br/>
The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). The selected timer can be adjusted here.
**Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.<br/>
| Board/CPU | Receive<br/>& PWM Timers| Hardware-PWM Pin | analogWrite()<br/>pins occupied by timer |
|--------------------------------------------------------------------------|-------------------|---------------------|-----------------------|
| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **1** | **6** |
| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **0**, 1 | **0**, 4 | **0**, 1 & 4 |
| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** |
| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **9**, 8 - 15 | **8 - 15** |
| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore) | **TCB0** | **PA05** |
| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore) | **TCA0** | **PA3** |
| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore) | **TCA0**, TCD | % |
| [ATmega8](https://github.com/MCUdude/MiniCore) | **1** | **9** |
| Board/CPU | Receive<br/>& send PWM Timer<br/>Default timer is **bold** | Hardware-Send-PWM Pin | analogWrite()<br/>pins occupied by timer |
|-|-|-|-|
| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x4.md) | **1** | **6** | |
| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x5.md) | **0**, 1 | **0**, 4 | **0**, 1 & 4 |
| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x8.md) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** |
| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x7.md) | **1** | **9**, 8 - 15 | **8 - 15** |
| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x04.md) | **TCB0** | **PA05** |
| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md) | **TCA0** | **PA3** |
| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x17.md) | **TCA0**, TCD | % |
| [ATmega8](https://github.com/MCUdude/MiniCore#supported-microcontrollers) | **1** | **9** |
| [ATmega1284](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2**, 3 | 13, 14, 6 |
| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2** | 13, **14** |
| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | **1** | **13** |
| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore#supported-microcontrollers) | **1** | **13** |
| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore#pinout ) | **1** | **13** |
| ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** |
| [ATmega1284](https://github.com/MCUdude/MightyCore) | 1, **2**, 3 | 13, 14, 6 |
| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 1, **2** | 13, **14** |
| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **1** | **13** |
| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore) | **1** | **13** |
| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore) | **1** | **13** |
| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 |
| ATmega4809 | **TCB0** | **A4** |
| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 |
| Zero (SAMD) | **TC3** | \*, **9** |
| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins |
| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 |
| ATmega1280, **ATmega2560** | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | 5, 6, **9**, 11, 46 |
| ATmega4809 | **TCB0** | **A4** | |
| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 |
| Zero (SAMD) | **TC3** | \*, **9** | |
| [ESP8266](http://esp8266.net/) | **timer1** | % | |
| [ESP32](http://esp32.net/) | **hw_timer_t**<br/>**Ledc channel 0** | All pins | |
| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | |
| [Teensy 1.0](https://www.pjrc.com/teensy/pinout.html) | **1** | **17** | 15, 18 |
| [Teensy 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, 3, **4_HS** | 9, **10**, 14 | 12 |
| [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, **2**, 3 | **1**, 16, 25 | 0 |
| [Teensy-LC](https://www.pjrc.com/teensy/pinout.html) | **TPM1** | **16** | 17 |
| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** |
| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | |
| [Teensy 4.0 - 4.1](https://www.pjrc.com/teensy/pinout.html) | **FlexPWM1.3** | **8** | 7, 25 |
| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** |
| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** |
| [BluePill / STM32F103C8T6](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill) | **TIM4** | % | **PB6 & PB7 & PB8 & PB9** |
| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin |
| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin |
| [RP2040 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin |
### No timer required for sending
@ -827,7 +890,7 @@ For other boards/platforms you must look for the appropriate section guarded by
### Stop and start timer
Another approach can be to share the timer **sequentially** if their functionality is used only for a short period of time like for the **Arduino tone() command**.
An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), where the timer settings for IR receive are restored after the tone has stopped.
For this we must call `IrReceiver.start()` or better `IrReceiver.start(microsecondsOfToneDuration)`.<br/>
For this we must call `IrReceiver.restartTimer()` or better `IrReceiver.restartTimer(microsecondsOfToneDuration)`.<br/>
This only works since each call to` tone()` completely initializes the timer 2 used by the `tone()` command.
## Hardware-PWM signal generation for sending
@ -837,7 +900,7 @@ Since each hardware timer has its dedicated output pin(s), you must change timer
**Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/39bdf8d7bf5b90dc221f8ae9fb3efed9f0a8a1db/examples/SimpleSender/PinDefinitionsAndMore.h#L273), where **PWM generation does not require a timer**.
## Why do we use 30% duty cycle for sending
We do it according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf):
We [do it](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRSend.hpp#L1192) according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf):
- Carrier duty cycle 50 %, peak current of emitter IF = 200 mA, the resulting transmission distance is 25 m.
- Carrier duty cycle 10 %, peak current of emitter IF = 800 mA, the resulting transmission distance is 29 m. - Factor 1.16
The reason is, that it is not the pure energy of the fundamental which is responsible for the receiver to detect a signal.
@ -850,7 +913,8 @@ The IR signal is sampled at a **50 &micro;s interval**. For a constant 525 &micr
And believe me, if you send a 525 &micro;s signal, your receiver will output something between around 400 and 700 &micro;s!<br/>
Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).<br/>
E.g. for the NEC protocol with its 560 &micro;s unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 &micro;s and 15 ticks / 750 &micro;s (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.<br/>
And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value]/https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown)
And since the receivers generated marks are longer or shorter than the spaces,
we have introduced the [`MARK_EXCESS_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) macro
to compensate for this receiver (and signal strength as well as ambient light dependent :disappointed: ) specific deviation.<br/>
Welcome to the world of **real world signal processing**.
@ -866,16 +930,16 @@ Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.<br/>
<br/>
# Quick comparison of 5 Arduino IR receiving libraries
[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**.
**This is a short comparison and may not be complete or correct.**
I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.<br/>
It is dated from **24.06.2022**. If you have complains about the data or request for extensions, please send a PM or open a discussion.
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.
| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)<br/>**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [Minimal NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
|---------|------|-----------|--------|----------|----------|----------|
| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC | NEC + RC5 + Sony + Samsung |
[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**.
| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)<br/>**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver/TinyReceiver.ino) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
|-|-|-|-|-|-|-|
| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC + FAST | NEC + RC5 + Sony + Samsung |
| Timing method receive | Timer2 or interrupt for pin 2 or 3 | **Interrupt** | Timer2 or interrupt for pin 2 or 3 | Timer2 | **Interrupt** | **Interrupt** |
| Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay<br/>Microseconds() | blocking wait with delay<br/>Microseconds() | % |
| Send pins| All | All | All ? | Timer dependent | All | % |
@ -887,30 +951,35 @@ It is dated from **24.06.2022**. If you have complains about the data or request
| FLASH usage (simple NEC example with 5 prints) | 1820<br/>(4300 for 15 main / 8000 for all 40 protocols)<br/>(+200 for callback)<br/>(+80 for interrupt at pin 2+3)| 1270<br/>(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? |
| RAM usage | 52<br/>(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 |
| Supported platforms | **avr, megaavr, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3<br/>(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attach<br/>Interrupt()** | **All platforms with attach<br/>Interrupt()** |
| Last library update | 6/2022 | 4/2018 | 3/2022 | 6/2022 | 6/2022 | 2/2022 |
| Remarks | Decodes 40 protocols concurrently.<br/>39 Protocols to send.<br/>Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 45 issues, no reaction for at least one year.** | Universal decoder and encoder.<br/>Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. |
| Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 |
| Remarks | Decodes 40 protocols concurrently.<br/>39 Protocols to send.<br/>Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 63 issues, 10 pull requests.* | Universal decoder and encoder.<br/>Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. |
\* The Hash protocol gives you a hash as code, which may be sufficient to distinguish your keys on the remote, but may not work with some protocols like Mitsubishi
<br/>
# [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md)
# Useful links
- [List of public IR code databases](http://www.harctoolbox.org/IR-resources.html)
- [LIRC database](http://lirc-remotes.sourceforge.net/remotes-table.html)
- [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols)
- [IRDB database for IR codes](https://github.com/probonopd/irdb/tree/master/codes)
- [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols)
- [Good introduction to IR remotes by DroneBot Workshop](https://dronebotworkshop.com/ir-remotes/)
- [IR Remote Control Theory and some protocols (upper right hamburger icon)](https://www.sbprojects.net/knowledge/ir/)
- [Interpreting Decoded IR Signals (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html)
- ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino)
- The original blog post of Ken Shirriff [A Multi-Protocol Infrared Remote Library for the Arduino](http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html)
- [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf)
# [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md)
# License
Up to the version 2.7.0, the License is GPLv2.
From the version 2.8.0, the license is the MIT license.
# Copyright
Initially coded 2009 Ken Shirriff http://www.righto.com<br/>
Copyright (c) 2016-2017 Rafi Khan<br/>
Copyright (c) 2020-2023 [Armin Joachimsmeyer](https://github.com/ArminJo)
Copyright (c) 2016-2017 Rafi Khan https://rafikhan.io<br/>
Copyright (c) 2020-2024 [Armin Joachimsmeyer](https://github.com/ArminJo)

View File

@ -2,6 +2,35 @@
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
# 4.3.2
- Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent.
- Added sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent.
# 4.3.1
- Fixed overflow bug for rawlen > 254.
- Removed deprecated sendPulseDistance... functions with parameter aSendStopBit.
# 4.3.0
- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin).
Therefore IrSender.begin(DISABLE_LED_FEEDBACK) will not longer work!
- Added convenience function isIRReceiverAttachedForTinyReceiver().
- Added Extended NEC Protocol macro to TinyIR by Buzzerb.
- Fixed sendSamsung() / sendSamsungLG() bug.
- Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd().
- Added rawlen and initialGap to IRData.
- Added ReceiveAndSendHobToHood example.
- Changed RECORD_GAP_MICROS default value from 5000 to 8000.
# 4.2.1
- Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp.
- TinyReceiver 2.0
- New TinyIRReceiverData which is filled with address, command and flags.
- Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal().
- Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated.
- Fix changing IR_SEND_PIN dynamically for ESP32.
- Fix wrong type of tEnableLEDFeedback.
- Support for ESP32-C3.
# 4.2.0
- The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message.
- Added DECODE_ONKYO, to force 16 bit command and data decoding.

View File

@ -85,6 +85,7 @@
#define ADC_TEMPERATURE_CHANNEL_MUX 15
#define ADC_1_1_VOLT_CHANNEL_MUX 12
#define ADC_GND_CHANNEL_MUX 13
#define ADC_CHANNEL_MUX_MASK 0x0F
#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define ADC_ISCR_CHANNEL_MUX 3
@ -92,56 +93,100 @@
#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_ATmega32U4__)
#define ADC_TEMPERATURE_CHANNEL_MUX 0x27
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x3F
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E
#define ADC_GND_CHANNEL_MUX 0x1F
#define ADC_CHANNEL_MUX_MASK 0x1F
#define INTERNAL INTERNAL1V1
#else
#error "No temperature channel definitions specified for this AVR CPU"
#endif
extern float sVCCVoltage;
extern uint16_t sVCCVoltageMillivolt;
/*
* Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion)
*
* Default values are suitable for Li-ion batteries.
* We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
* But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
*/
#if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
#endif
#if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
#endif
#if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5250 // + 5 % operation voltage
#endif
#if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5500 // +10 %. Max recommended operation voltage
#endif
#if !defined(VCC_CHECK_PERIOD_MILLIS)
#define VCC_CHECK_PERIOD_MILLIS 10000L // 10 seconds period of VCC checks
#endif
#if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP)
#define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4300 // Assume USB powered above this voltage
#endif
#if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT 4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN.
// In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply
#endif
extern long sLastVCCCheckMillis;
extern uint8_t sVCCTooLowCounter;
uint16_t readADCChannel(uint8_t aChannelNumber);
uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithOversample(uint8_t aChannelNumber, uint8_t aOversampleExponent);
void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference,
uint8_t aMaxRetries);
uint16_t readADCChannel(uint8_t aADCChannelNumber);
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
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);
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference);
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference);
/*
* readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage
*/
float getVCCVoltageSimple(void);
void readVCCVoltageSimple(void);
uint16_t getVCCVoltageMillivoltSimple(void);
void readVCCVoltageMillivoltSimple(void);
float getVCCVoltage(void);
void readVCCVoltage(void);
uint16_t getVCCVoltageMillivolt(void);
void readVCCVoltageMillivolt(void);
@ -152,14 +197,31 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial);
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement);
float getTemperatureSimple(void);
float getTemperature(void);
float getCPUTemperatureSimple(void);
float getCPUTemperature(void);
float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated
bool isVCCTooLowMultipleTimes();
void resetVCCTooLowMultipleTimes();
bool isVCCTooLow();
bool isVCCTooHigh();
bool isVCCTooHighSimple();
bool isVCCUSBPowered();
bool isVCCUSBPowered(Print *aSerial);
bool isVCCUndervoltageMultipleTimes();
void resetCounterForVCCUndervoltageMultipleTimes();
bool isVCCUndervoltage();
bool isVCCEmergencyUndervoltage();
bool isVCCOvervoltage();
bool isVCCOvervoltageSimple();
#endif // defined(__AVR__) ...
/*
* Variables and functions defined as dummies to allow for seamless compiling on non AVR platforms
*/
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

View File

@ -3,7 +3,7 @@
*
* ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h.
*
* Copyright (C) 2016-2022 Armin Joachimsmeyer
* Copyright (C) 2016-2023 Armin Joachimsmeyer
* Email: armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
@ -26,7 +26,7 @@
#define _ADC_UTILS_HPP
#include "ADCUtils.h"
#if defined(ADC_UTILS_ARE_AVAILABLE)
#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
@ -54,6 +54,16 @@ union WordUnionForADCUtils {
uint8_t *BytePointer;
};
/*
* Enable this to see information on each call.
* Since there should be no library which uses Serial, it should only be enabled for development purposes.
*/
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/*
* Persistent storage for VCC value
*/
@ -67,9 +77,9 @@ uint8_t sVCCTooLowCounter = 0;
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
*/
uint16_t readADCChannel(uint8_t aChannelNumber) {
uint16_t readADCChannel(uint8_t aADCChannelNumber) {
WordUnionForADCUtils tUValue;
ADMUX = aChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
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
@ -88,9 +98,9 @@ uint16_t readADCChannel(uint8_t aChannelNumber) {
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
*/
uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference) {
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
WordUnionForADCUtils tUValue;
ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
@ -109,18 +119,18 @@ uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference)
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
* Does NOT restore ADMUX after reading
*/
uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference) {
checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference);
return readADCChannelWithReference(aChannelNumber, aReference);
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
return readADCChannelWithReference(aADCChannelNumber, aReference);
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
* Restores ADMUX after reading
*/
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aChannelNumber, uint8_t aReference) {
uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference);
uint16_t tResult = readADCChannelWithReference(aChannelNumber, aReference);
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference) {
uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
uint16_t tResult = readADCChannelWithReference(aADCChannelNumber, aReference);
checkAndWaitForReferenceAndChannelToSwitch(tOldADMUX & MASK_FOR_ADC_CHANNELS, tOldADMUX >> SHIFT_VALUE_FOR_REFERENCE);
return tResult;
}
@ -128,15 +138,15 @@ uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t a
/*
* To prepare reference and ADMUX for next measurement
*/
void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference) {
ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference) {
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
}
/*
* @return original ADMUX register content for optional later restoring values
* All experimental values are acquired by using the ADCSwitchingTest example from this library
*/
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference) {
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference) {
uint8_t tOldADMUX = ADMUX;
/*
* Must wait >= 7 us if reference has to be switched from 1.1 volt/INTERNAL to VCC/DEFAULT (seen on oscilloscope)
@ -146,18 +156,21 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8
* Must wait >= 200 us if channel has to be switched to 1.1 volt internal channel if S&H was at 5 Volt
*/
uint8_t tNewReference = (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aChannelNumber | tNewReference;
ADMUX = aADCChannelNumber | tNewReference;
#if defined(INTERNAL2V56)
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) {
#else
if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) {
#endif
#if defined(LOCAL_DEBUG)
Serial.println(F("Switch from DEFAULT to INTERNAL"));
#endif
/*
* Switch reference from DEFAULT to INTERNAL
*/
delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board
} else if ((tOldADMUX & 0x0F) != aChannelNumber) {
if (aChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
} else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK) != aADCChannelNumber) {
if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
/*
* Internal 1.1 Volt channel requires <= 200 us for Nano board
*/
@ -176,16 +189,16 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8
* Oversample and multiple samples only makes sense if you expect a noisy input signal
* It does NOT increase the precision of the measurement, since the ADC has insignificant noise
*/
uint16_t readADCChannelWithOversample(uint8_t aChannelNumber, uint8_t aOversampleExponent) {
return readADCChannelWithReferenceOversample(aChannelNumber, DEFAULT, aOversampleExponent);
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent) {
return readADCChannelWithReferenceOversample(aADCChannelNumber, DEFAULT, aOversampleExponent);
}
/*
* Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
*/
uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
@ -212,9 +225,9 @@ uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t a
/*
* Use ADC_PRESCALE32 which gives 26 us conversion time and good linearity for 16 MHz Arduino
*/
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
uint16_t tSumValue = 0;
ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
@ -239,11 +252,12 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8
/*
* Returns sum of all sample values
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h.
* Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h.
* @ param aNumberOfSamples If > 64 an overflow may occur.
*/
uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
uint16_t tSumValue = 0;
ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
@ -266,13 +280,72 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t
}
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
* @return the maximum of aNumberOfSamples measurements.
* 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.
*/
uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) {
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 = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
// ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
@ -298,33 +371,41 @@ uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReferen
/*
* use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
* @return the maximum value during aMicrosecondsToAquire measurement.
*/
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
uint16_t tNumberOfSamples = aMicrosecondsToAquire / 26;
return readADCChannelWithReferenceMax(aChannelNumber, aReference, tNumberOfSamples);
return readADCChannelWithReferenceMax(aADCChannelNumber, aReference, tNumberOfSamples);
}
/*
* aMaxRetries = 255 -> try forever
* @return (tMax + tMin) / 2
*/
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference,
uint8_t aMaxRetries) {
int tValues[4];
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
uint8_t aAllowedDifference, uint8_t aMaxRetries) {
int tValues[4]; // last value is in tValues[3]
int tMin;
int tMax;
tValues[0] = readADCChannel(aChannelNumber);
/*
* Initialize first 4 values before checking
*/
tValues[0] = readADCChannelWithReference(aADCChannelNumber, aReference);
for (int i = 1; i < 4; ++i) {
delay(aDelay); // Only 3 delays!
tValues[i] = readADCChannel(aChannelNumber);
if (aDelay != 0) {
delay(aDelay); // Minimum is only 3 delays!
}
tValues[i] = readADCChannelWithReference(aADCChannelNumber, aReference);
}
do {
// find min and max
/*
* Get min and max of the last 4 values
*/
tMin = 1024;
tMax = 0;
for (int i = 0; i < 4; ++i) {
for (uint_fast8_t i = 0; i < 4; ++i) {
if (tValues[i] < tMin) {
tMin = tValues[i];
}
@ -338,22 +419,44 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe
if ((tMax - tMin) <= aAllowedDifference) {
break;
} else {
/*
* Get next value
*/
// Serial.print("Difference=");
// Serial.println(tMax - tMin);
// move values
// Move values to front
for (int i = 0; i < 3; ++i) {
tValues[i] = tValues[i + 1];
}
// and wait
delay(aDelay);
tValues[3] = readADCChannel(aChannelNumber);
// and wait before getting next value
if (aDelay != 0) {
delay(aDelay);
}
tValues[3] = readADCChannelWithReference(aADCChannelNumber, aReference);
}
if (aMaxRetries != 255) {
aMaxRetries--;
}
} while (aMaxRetries > 0);
#if defined(LOCAL_DEBUG)
if(aMaxRetries == 0) {
Serial.print(F("No 4 equal values for difference "));
Serial.print(aAllowedDifference);
Serial.print(F(" found "));
Serial.print(tValues[0]);
Serial.print(' ');
Serial.print(tValues[1]);
Serial.print(' ');
Serial.print(tValues[2]);
Serial.print(' ');
Serial.println(tValues[3]);
} else {
Serial.print(aMaxRetries);
Serial.println(F(" retries left"));
}
#endif
return (tMax + tMin) / 2;
}
@ -368,7 +471,7 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe
*/
float getVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return ((1023 * 1.1 * 4) / tVCC);
}
@ -379,7 +482,7 @@ float getVCCVoltageSimple(void) {
*/
uint16_t getVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
}
@ -419,6 +522,9 @@ uint16_t getVCCVoltageMillivolt(void) {
return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
}
/*
* Does not set sVCCVoltageMillivolt
*/
uint16_t printVCCVoltageMillivolt(Print *aSerial) {
aSerial->print(F("VCC="));
uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt();
@ -440,8 +546,8 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
*/
void readVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltage = (1023 * 1.1 * 4) / tVCC;
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltage = (1023 * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}
/*
@ -451,7 +557,7 @@ void readVCCVoltageSimple(void) {
*/
void readVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}
@ -500,33 +606,37 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM
}
/*
* Default values are suitable for Li-ion batteries.
* We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
* But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
*/
#if !defined(VCC_STOP_THRESHOLD_MILLIVOLT)
#define VCC_STOP_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby
#endif
#if !defined(VCC_EMERGENCY_STOP_MILLIVOLT)
#define VCC_EMERGENCY_STOP_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt
#endif
#if !defined(VCC_TOO_HIGH_STOP_MILLIVOLT)
#define VCC_TOO_HIGH_STOP_MILLIVOLT 5250 // + 5 % operation voltage
#endif
#if !defined(VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT)
#define VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT 5500 // +10 %. Max recommended operation voltage
#endif
#if !defined(VCC_CHECK_PERIOD_MILLIS)
#define VCC_CHECK_PERIOD_MILLIS 10000 // Period of VCC checks
#endif
#if !defined(VCC_CHECKS_TOO_LOW_BEFORE_STOP)
#define VCC_CHECKS_TOO_LOW_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_STOP_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_STOP_MILLIVOLT
#endif
bool isVCCUSBPowered() {
readVCCVoltageMillivolt();
return (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT < sVCCVoltageMillivolt
&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT);
}
/*
* @ return true only once, when VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times voltage too low -> shutdown
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
*/
bool isVCCTooLowMultipleTimes() {
bool isVCCUSBPowered(Print *aSerial) {
readVCCVoltageMillivolt();
aSerial->print(F("USB powered is "));
bool tReturnValue;
if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT
< sVCCVoltageMillivolt&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
tReturnValue = true;
aSerial->print(F("true "));
} else {
tReturnValue = false;
aSerial->print(F("false "));
}
printVCCVoltageMillivolt(aSerial);
return tReturnValue;
}
/*
* @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown
*/
bool isVCCUndervoltageMultipleTimes() {
/*
* Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds
*/
@ -540,33 +650,35 @@ bool isVCCTooLowMultipleTimes() {
readVCCVoltageMillivolt();
# endif
if (sVCCTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
/*
* Do not check again if shutdown has happened
*/
if (sVCCVoltageMillivolt > VCC_STOP_THRESHOLD_MILLIVOLT) {
if (sVCCVoltageMillivolt > VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
sVCCTooLowCounter = 0; // reset counter
} else {
/*
* Voltage too low, wait VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times and then shut down.
* Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then shut down.
*/
if (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT) {
if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
// emergency shutdown
sVCCTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP;
sVCCTooLowCounter = VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP;
# if defined(INFO)
Serial.println(F("Voltage < " STR(VCC_EMERGENCY_STOP_MILLIVOLT) " mV detected -> emergency shutdown"));
Serial.println(
F(
"Voltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown"));
# endif
} else {
sVCCTooLowCounter++;
# if defined(INFO)
Serial.print(F("Voltage < " STR(VCC_STOP_THRESHOLD_MILLIVOLT) " mV detected: "));
Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVCCTooLowCounter);
Serial.print(F("Voltage < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected: "));
Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter);
Serial.println(F(" tries left"));
# endif
}
if (sVCCTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) {
if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
/*
* 6 times voltage too low -> shutdown
* 6 times voltage too low -> return signal for shutdown etc.
*/
return true;
}
@ -576,16 +688,23 @@ bool isVCCTooLowMultipleTimes() {
return false;
}
/*
* Return true if VCC_EMERGENCY_STOP_MILLIVOLT (3 V) reached
* Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached
*/
bool isVCCTooLow(){
return (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT);
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 resetVCCTooLowMultipleTimes(){
void resetCounterForVCCUndervoltageMultipleTimes() {
sVCCTooLowCounter = 0;
}
@ -598,48 +717,83 @@ void resetVCCTooLowMultipleTimes(){
* Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
* @return true if 5 % overvoltage reached
*/
bool isVCCTooHigh(){
bool isVCCOvervoltage() {
readVCCVoltageMillivolt();
return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT);
return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}
bool isVCCTooHighSimple(){
bool isVCCOvervoltageSimple() {
readVCCVoltageMillivoltSimple();
return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT);
return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}
/*
* Temperature sensor is enabled by selecting the appropriate channel.
* Different formula for 328P and 328PB!
* !!! Function without handling of switched reference and channel.!!!
* Use it ONLY if you only use INTERNAL reference (call getTemperatureSimple()) in your program.
* Use it ONLY if you only use INTERNAL reference (e.g. only call getTemperatureSimple()) in your program.
*/
float getTemperatureSimple(void) {
float getCPUTemperatureSimple(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
return 0.0;
#else
// use internal 1.1 volt as reference
float tTemp = (readADCChannelWithReferenceMultiSamples(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2) - 317);
return (tTemp * (4 / 1.22));
// use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-(
uint16_t tTempRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2);
#if defined(LOCAL_DEBUG)
Serial.print(F("TempRaw="));
Serial.println(tTempRaw);
#endif
#if defined(__AVR_ATmega328PB__)
tTempRaw -= 245;
return (float)tTempRaw;
#else
tTempRaw -= 317;
return (float) tTempRaw / 1.22;
#endif
#endif
}
/*
* Handles reference and channel switching by introducing the appropriate delays.
* Handles usage of 1.1 V reference and channel switching by introducing the appropriate delays.
*/
float getTemperature(void) {
return getCPUTemperature();
}
float getCPUTemperature(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
return 0.0;
#else
// use internal 1.1 volt as reference
checkAndWaitForReferenceAndChannelToSwitch(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL);
// assume the signal has noise, but never verified :-(
float tTemp = (readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 1) - 317);
return (tTemp / 1.22);
return getCPUTemperatureSimple();
#endif
}
#elif defined(ARDUINO_ARCH_APOLLO3) // defined(ADC_UTILS_ARE_AVAILABLE)
void ADCUtilsDummyToAvoidBFDAssertions(){
;
}
#else // defined(ADC_UTILS_ARE_AVAILABLE)
// Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors
/*
* Persistent storage for VCC value
*/
float sVCCVoltage;
uint16_t sVCCVoltageMillivolt;
uint16_t getVCCVoltageMillivoltSimple(void){
return 3300;
}
uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber __attribute__((unused)),
uint8_t aReference __attribute__((unused)), uint8_t aOversampleExponent __attribute__((unused))) {
return 0;
}
float getCPUTemperature() {
return 20.0;
}
float getVCCVoltage() {
return 3.3;
}
#endif // defined(ADC_UTILS_ARE_AVAILABLE)
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#endif // _ADC_UTILS_HPP

View File

@ -36,12 +36,13 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@ -59,7 +60,7 @@
// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols.
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
//#define DECODE_NEC // Includes Apple and Onkyo
@ -95,7 +96,9 @@ LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
#else
#define DEBUG_BUTTON_PIN 6
#endif
#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug
#if defined(__AVR_ATmega328P__)
#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug with pin 11
#endif
#define MILLIS_BETWEEN_ATTENTION_BEEP 60000 // 60 sec
uint32_t sMillisOfLastReceivedIRFrame = 0;
@ -103,7 +106,8 @@ uint32_t sMillisOfLastReceivedIRFrame = 0;
#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
#define USE_LCD
# if defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
// For cyclically display of VCC
// For cyclically display of VCC and isVCCUSBPowered()
#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4250
#include "ADCUtils.hpp"
#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
#define LCD_VOLTAGE_START_INDEX 11
@ -112,13 +116,12 @@ bool ProtocolStringOverwritesVoltage = false;
# endif
#define LCD_IR_COMMAND_START_INDEX 9
#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
void printsVCCVoltageMillivoltOnLCD();
void printIRResultOnLCD();
size_t printByteHexOnLCD(uint16_t aHexByteValue);
void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint);
uint16_t sVCCMillivolt;
#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
@ -164,8 +167,11 @@ void setup() {
# else
Serial.print(DEBUG_BUTTON_PIN);
# endif
Serial.print(F(" to ground or to pin "));
Serial.print(F(" to ground"));
# if defined(AUXILIARY_DEBUG_BUTTON_PIN)
Serial.print(F(" or to pin "));
Serial.print(AUXILIARY_DEBUG_BUTTON_PIN);
#endif
Serial.println(F(", raw data is always printed"));
// infos for receive
@ -175,8 +181,8 @@ void setup() {
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
#endif
#if defined(USE_LCD) && defined(__AVR__) && defined(ADCSRA) && defined(ADATE)
getVCCVoltageMillivoltSimple(); // to initialize ADC mux and reference
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
readVCCVoltageMillivolt();
#endif
#if defined(USE_SERIAL_LCD)
@ -196,7 +202,7 @@ void setup() {
#endif
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
sVCCMillivolt = getVCCVoltageMillivoltSimple();
readVCCVoltageMillivolt();
#endif
}
@ -226,17 +232,18 @@ void loop() {
} else {
// play tone
auto tStartMillis = millis();
IrReceiver.stop();
IrReceiver.stopTimer();
tone(TONE_PIN, 2200);
if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW)
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
&& sVCCMillivolt > 4222
|| isVCCUSBPowered()
#endif
) {
// Print more info, but only if we are connected to USB, i.e. VCC is > 4222 mV, because this may take to long to detect some fast repeats
) {
// Print more info, but only if we are connected to USB, i.e. VCC is > 4300 mV, because this may take to long to detect some fast repeats
IrReceiver.printIRSendUsage(&Serial);
IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-)
// IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-)
IrReceiver.printIRResultRawFormatted(&Serial); // print us, this is better to compare :-)
}
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
@ -246,7 +253,7 @@ void loop() {
noTone(TONE_PIN);
// Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
IrReceiver.restartTimerWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
#if defined(USE_LCD)
printIRResultOnLCD();
@ -261,15 +268,22 @@ void loop() {
} // if (IrReceiver.decode())
/*
* Check for attention every 10 minute, after the current measurement was finished
* Check if generating attention beep every minute, after the current measurement was finished
*/
if (millis() - sMillisOfLastReceivedIRFrame >= MILLIS_BETWEEN_ATTENTION_BEEP) {
if ((millis() - sMillisOfLastReceivedIRFrame) >= MILLIS_BETWEEN_ATTENTION_BEEP
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
&& !isVCCUSBPowered()
#endif
) {
sMillisOfLastReceivedIRFrame = millis();
IrReceiver.stop();
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
printsVCCVoltageMillivoltOnLCD();
#endif
IrReceiver.stopTimer();
tone(TONE_PIN, 2200);
delay(50);
noTone(TONE_PIN);
IrReceiver.startWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
IrReceiver.restartTimerWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
}
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
@ -279,18 +293,25 @@ void loop() {
* Periodically print VCC
*/
sMillisOfLastVoltagePrint = millis();
sVCCMillivolt = getVCCVoltageMillivoltSimple();
char tVoltageString[5];
dtostrf(sVCCMillivolt / 1000.0, 4, 2, tVoltageString);
myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
myLCD.print(' ');
myLCD.print(tVoltageString);
myLCD.print('V');
readVCCVoltageMillivolt();
printsVCCVoltageMillivoltOnLCD();
}
#endif
}
#if defined(USE_LCD)
void printsVCCVoltageMillivoltOnLCD() {
# if defined(ADC_UTILS_ARE_AVAILABLE)
char tVoltageString[5];
dtostrf(sVCCVoltageMillivolt / 1000.0, 4, 2, tVoltageString);
myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0);
myLCD.print(' ');
myLCD.print(tVoltageString);
myLCD.print('V');
# endif
}
/*
* LCD output for 1602 LCDs
* 40 - 55 Milliseconds per initial output
@ -300,7 +321,6 @@ void loop() {
*
*/
void printIRResultOnLCD() {
#if defined(USE_LCD)
static uint16_t sLastProtocolIndex = 4711;
static uint16_t sLastProtocolAddress = 4711;
static uint16_t sLastCommand = 0;
@ -336,18 +356,25 @@ void printIRResultOnLCD() {
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
/*
* Print number of bits received and microseconds of signal
* Print number of bits received and hash code or microseconds of signal
*/
myLCD.setCursor(0, 1);
uint8_t tNumberOfBits = (IrReceiver.decodedIRData.rawDataPtr->rawlen + 1) / 2;
if (tNumberOfBits < 10) {
myLCD.print(' '); // padding space
}
myLCD.print(tNumberOfBits);
uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits);
myLCD.print(F(" bit "));
uint_fast8_t tDurationStringLength = myLCD.print(IrReceiver.getTotalDurationOfRawData());
myLCD.print(F(" \xE4s")); // \xE4 is micro symbol
printSpacesOnLCD(7 - tDurationStringLength);
if (IrReceiver.decodedIRData.decodedRawData != 0) {
if (tNumberOfBits < 10) {
myLCD.print('0');
tPrintedStringLength++;
}
myLCD.print('x');
tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX) + 1;
} else {
tPrintedStringLength += myLCD.print(IrReceiver.getTotalDurationOfRawData());
myLCD.print(F(" \xE4s")); // \xE4 is micro symbol
}
printSpacesOnLCD(11 - tPrintedStringLength);
sLastProtocolAddress = 4711;
sLastCommand = 44711;
@ -416,10 +443,8 @@ void printIRResultOnLCD() {
myLCD.print(' ');
}
} // IrReceiver.decodedIRData.protocol == UNKNOWN
#endif // defined(USE_LCD)
}
#if defined(USE_LCD)
size_t printByteHexOnLCD(uint16_t aHexByteValue) {
myLCD.print(F("0x"));
size_t tPrintSize = 2;
@ -435,4 +460,4 @@ void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint) {
myLCD.print(' ');
}
}
#endif
#endif // defined(USE_LCD)

View File

@ -1,4 +1,12 @@
// 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
*/
#include "Arduino.h"
@ -23,6 +31,18 @@ inline size_t LiquidCrystal_I2C::write(uint8_t value) {
#include "SoftWire.h"
#endif
#if defined(__AVR__)
/*
* The datasheet says: a command need > 37us to settle. Enable pulse must be > 450ns.
* Use no delay for enable pulse after each command,
* because the overhead of this library seems to be using the 37 us and 450 ns.
* At least it works perfectly for all my LCD's connected to Uno, Nano etc.
* and it saves a lot of time in realtime applications using LCD as display,
* like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter
*/
#define USE_FAST_TIMING
#endif
// When the display powers up, it is configured as follows:
//
// 1. Display clear
@ -131,7 +151,11 @@ void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t line
/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear() {
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
#if defined(USE_FAST_TIMING)
delayMicroseconds(1500); // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK
#else
delayMicroseconds(2000); // this command takes a long time!
#endif
if (_oled)
setCursor(0, 0);
}
@ -274,10 +298,13 @@ void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
expanderWrite(_data | En); // En high
delayMicroseconds(1); // enable pulse must be >450ns
#if !defined(USE_FAST_TIMING)
delayMicroseconds(1); // enable pulse must be > 450ns // AJ 20.9.23 not required for my LCD's
#endif
expanderWrite(_data & ~En); // En low
delayMicroseconds(50); // commands need > 37us to settle
#if !defined(USE_FAST_TIMING)
delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's
#endif
}
// Alias functions

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -35,7 +35,7 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if FLASHEND <= 0x1FFF || (RAMEND <= 0x4FF || RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167
#if FLASHEND <= 0x1FFF || (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167
#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
#define EXCLUDE_EXOTIC_PROTOCOLS
#endif

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -5,14 +5,14 @@
*
* To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I"
*
* Copyright (C) 2019-2021 Armin Joachimsmeyer
* Copyright (C) 2019-2024 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* ServoEasing is free software: you can redistribute it and/or modify
* 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.
@ -38,6 +38,22 @@
#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
// Basic mapping structure
struct IRToCommandMappingStruct {
@ -72,13 +88,10 @@ struct IRDataForCommandDispatcherStruct {
#define COMMAND_EMPTY 0xFF // code no command
#endif
#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return
#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break
#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return
class IRCommandDispatcher {
public:
void init();
void printIRInfo(Print *aSerial);
bool checkAndRunNonBlockingCommands();
bool checkAndRunSuspendedBlockingCommands();
@ -107,7 +120,8 @@ public:
bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command
/*
* Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP).
* Is reset by next IR command received. Can be reset by main loop, if command has stopped.
* 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;
/*

View File

@ -11,14 +11,14 @@
* A blocking command is stored and sets a stop flag for an already running blocking function to terminate.
* The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands().
*
* Copyright (C) 2019-2022 Armin Joachimsmeyer
* Copyright (C) 2019-2024 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* ServoEasing is free software: you can redistribute it and/or modify
* 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.
@ -31,6 +31,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
/*
* Program behavior is modified by the following macros
* USE_TINY_IR_RECEIVER
* USE_IRMP_LIBRARY
* IR_COMMAND_HAS_MORE_THAN_8_BIT
*/
#ifndef _IR_COMMAND_DISPATCHER_HPP
#define _IR_COMMAND_DISPATCHER_HPP
@ -38,6 +46,10 @@
#include "IRCommandDispatcher.h"
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
/*
* 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.
@ -57,9 +69,6 @@
IRCommandDispatcher IRDispatcher;
#if defined(USE_TINY_IR_RECEIVER)
#include "TinyIRReceiver.hpp" // included in "IRremote" library
#if defined(LOCAL_INFO)
#define CD_INFO_PRINT(...) Serial.print(__VA_ARGS__);
#define CD_INFO_PRINTLN(...) Serial.println(__VA_ARGS__);
@ -68,33 +77,43 @@ IRCommandDispatcher IRDispatcher;
#define CD_INFO_PRINTLN(...) void();
#endif
#if defined(USE_TINY_IR_RECEIVER)
#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // included in "IRremote" library
void IRCommandDispatcher::init() {
initPCIInterruptForTinyReceiver();
}
/*
* @return true, if IR Receiver is attached
*/
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
aSerial->print(F("Listening to IR remote of type "));
aSerial->print(IR_REMOTE_NAME);
aSerial->println(F(" at pin " STR(IR_RECEIVE_PIN)));
}
/*
* This is the TinyReceiver callback function, which is called if a complete command was received
* It checks for right address and then call the dispatcher
*/
#if defined(ESP8266) || defined(ESP32)
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) {
IRDispatcher.IRReceivedData.address = aAddress;
IRDispatcher.IRReceivedData.command = aCommand;
IRDispatcher.IRReceivedData.isRepeat = aFlags & IRDATA_FLAGS_IS_REPEAT;
# 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();
CD_INFO_PRINT(F("A=0x"));
CD_INFO_PRINT(aAddress, HEX);
CD_INFO_PRINT(F(" C=0x"));
CD_INFO_PRINT(aCommand, HEX);
if (IRDispatcher.IRReceivedData.isRepeat) {
CD_INFO_PRINT(F("R"));
}
CD_INFO_PRINTLN();
# if defined(LOCAL_INFO)
printTinyReceiverResultMinimal(&Serial);
# endif
if (aAddress == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
if (TinyIRReceiverData.Address == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h
IRDispatcher.IRReceivedData.isAvailable = true;
if(!IRDispatcher.doNotUseDispatcher) {
/*
@ -157,11 +176,11 @@ void handleReceivedIRData() {
#endif // elif defined(USE_IRMP_LIBRARY)
/*
* The main dispatcher function
* Sets flags justCalledRegularIRCommand, executingBlockingCommand
* @param aCallBlockingCommandImmediately Run blocking command directly, otherwise set request to stop to true
* and store command for main loop to execute by checkAndRunSuspendedBlockingCommands().
* Should be false if called by ISR.
* The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands()
* Non blocking commands are executed directly, blocking commands are executed if enabled by parameter and no other command is just running.
* Otherwise request to stop (requestToStopReceived) is set and command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands().
* 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.
*/
void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) {
if (IRReceivedData.command == COMMAND_EMPTY) {
@ -204,21 +223,31 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
}
/*
* lets start a new turn
* Execute commands
*/
requestToStopReceived = false;
bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING);
if (tIsNonBlockingCommand) {
// short command here, just call
CD_INFO_PRINT(F("Run non blocking command: "));
CD_INFO_PRINTLN (tCommandName);
CD_INFO_PRINTLN(tCommandName);
#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(BUZZER_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
} else {
/*
* Blocking command here
*/
if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) {
/*
* here we are called from main loop to execute a command
* 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
@ -226,7 +255,16 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
* This call is blocking!!!
*/
CD_INFO_PRINT(F("Run blocking command: "));
CD_INFO_PRINTLN (tCommandName);
CD_INFO_PRINTLN(tCommandName);
#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER)
/*
* Do (non blocking) buzzer feedback before command is executed
*/
if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) {
tone(BUZZER_PIN, 2200, 50);
}
#endif
IRMapping[i].CommandToCall();
#if defined(TRACE)
@ -235,12 +273,14 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate
currentBlockingCommandCalled = COMMAND_EMPTY;
} else {
/*
* Do not run command directly, but set request to stop to true and store command for main loop to execute
* 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
CD_INFO_PRINT(F("Requested stop and stored blocking command "));
CD_INFO_PRINT (tCommandName);
CD_INFO_PRINT(tCommandName);
CD_INFO_PRINTLN(F(" as next command to run."));
}
}
@ -260,25 +300,29 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() {
*/
if (BlockingCommandToRunNext != COMMAND_EMPTY) {
CD_INFO_PRINT(F("Take stored command = 0x"));
CD_INFO_PRINT(F("Run stored command=0x"));
CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX);
IRReceivedData.command = BlockingCommandToRunNext;
BlockingCommandToRunNext = COMMAND_EMPTY;
IRReceivedData.isRepeat = false;
requestToStopReceived = false; // Do not stop the command executed now
checkAndCallCommand(true);
return true;
}
return false;
}
/*
* Not used internally
*/
#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT)
void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunNext)
#else
void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext)
#endif
{
CD_INFO_PRINT(F("Set next command to 0x"));
CD_INFO_PRINT(F("Set next command to run to 0x"));
CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX);
BlockingCommandToRunNext = aBlockingCommandToRunNext;
requestToStopReceived = true;
@ -300,7 +344,6 @@ bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) {
}
void IRCommandDispatcher::printIRCommandString(Print *aSerial) {
aSerial->print(F("IRCommand="));
for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) {
if (IRReceivedData.command == IRMapping[i].IRCode) {
aSerial->println(reinterpret_cast<const __FlashStringHelper*>(IRMapping[i].CommandString));

View File

@ -49,37 +49,11 @@
#if defined(USE_TINY_IR_RECEIVER)
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
/*
* Set sensible receive pin for different CPU's
*/
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IR_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9
# else
#define IR_INPUT_PIN 0 // PCINT0
# endif
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IR_INPUT_PIN 10
# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#define IR_INPUT_PIN 21 // INT0
# elif defined(ESP8266)
#define IR_INPUT_PIN 14 // D5
# elif defined(ESP32)
#define IR_INPUT_PIN 15
# elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
#define IR_INPUT_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
# elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
# else
#define IR_INPUT_PIN 2 // INT0
# endif
#elif defined(USE_IRMP_LIBRARY)
/*
* IRMP version
*/
#define IR_INPUT_PIN 2
#define IR_RECEIVE_PIN 2
#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used.
#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN
@ -159,7 +133,7 @@ void setup() {
IRDispatcher.init(); // This just calls irmp_init()
#if defined(USE_TINY_IR_RECEIVER)
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN)));
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN)));
#else
irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2021 Armin Joachimsmeyer
* Copyright (c) 2021-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
@ -31,11 +31,34 @@
*/
#include <Arduino.h>
/*
* !!! The value of RAW_BUFFER_LENGTH (and some other macros) must be the same in all compile units !!!
* Otherwise you may get warnings like "type 'struct IRData' itself violates the C++ One Definition Rule"
*/
#if !defined(RAW_BUFFER_LENGTH)
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750
# endif
#endif
#include "IRremoteExtensionClass.h"
IRExtensionClass::IRExtensionClass(IRrecv *aIrReceiver) {
MyIrReceiver = aIrReceiver;
}
bool IRExtensionClass::decode() {
return MyIrReceiver->decode();
}
bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
return MyIrReceiver->printIRResultShort(aSerial,aPrintRepeatGap,aCheckForRecordGapsMicros);
}
void IRExtensionClass::resume() {
Serial.println(F("Call resume()"));
MyIrReceiver->resume();

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2021 Armin Joachimsmeyer
* Copyright (c) 2021-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
@ -39,6 +39,8 @@ class IRExtensionClass
public:
IRrecv * MyIrReceiver;
IRExtensionClass(IRrecv * aIrReceiver);
bool decode();
bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap = true, bool aCheckForRecordGapsMicros = true);
void resume();
};

View File

@ -33,12 +33,13 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@ -70,8 +71,8 @@ void setup() {
}
void loop() {
if (IrReceiver.decode()) {
IrReceiver.printIRResultShort(&Serial);
if (IRExtension.decode()) {
IRExtension.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
IRExtension.resume(); // Use the extended function provided by IRExtension class
}

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -67,12 +67,13 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@ -317,7 +318,7 @@ void setup() {
#endif
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
#endif

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -14,6 +14,7 @@
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
* See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSend_Code
*
* Initially coded 2009 Ken Shirriff http://www.righto.com
*
@ -22,7 +23,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2009-2023 Ken Shirriff, Armin Joachimsmeyer
* Copyright (c) 2009-2024 Ken Shirriff, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -69,11 +70,15 @@
//#define DECODE_WHYNTER
//#define DECODE_FAST
//
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 120
# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 120 // 180 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
# elif (defined(RAMEND) && RAMEND <= 0xAFF) || (defined(RAMSIZE) && RAMSIZE < 0xAFF)
#define RAW_BUFFER_LENGTH 500 // 750 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
# else
#define RAW_BUFFER_LENGTH 750
# endif
@ -82,7 +87,7 @@
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -127,7 +132,7 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -16,6 +16,7 @@
* A button must be connected between the input SEND_BUTTON_PIN and ground.
* A visible LED can be connected to STATUS_PIN to provide status.
*
* See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSendDistanceWidth_Code
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@ -56,17 +57,18 @@
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 120
# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO
#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH];
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -79,8 +81,8 @@
#define DELAY_BETWEEN_REPEATS_MILLIS 70
// Storage for the recorded code, pre-filled with NEC data
IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // address 0x12 command 0x34
DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // NEC timing
IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34
DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing
uint8_t sNumberOfBits = 32;
bool sSendButtonWasActive;
@ -99,7 +101,7 @@ void setup() {
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}

View File

@ -0,0 +1,341 @@
/*
* 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-2023 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 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
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
#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
# 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__) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
#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__) // 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#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__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA1 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
#define APPLICATION_PIN PIN_PB2 // 5
#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
# elif defined(__AVR_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(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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
// tone() is included in ESP32 core since 2.0.2
#if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
#endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_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
#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) // !!!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)
#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
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids 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
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif

View File

@ -0,0 +1,143 @@
/*
* ReceiveAndSendHob2Hood.cpp
*
* Demonstrates receiving and sending of IR codes for AEG / Elektrolux Hob2Hood protocol
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
************************************************************************************
*/
#include <Arduino.h>
#define DECODE_HASH // Only decoder, which works for Hob2Hood. protocol is UNKNOWN and only raw data is set.
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>
// IR commands from AEG hob2hood device
#define NUMBER_OF_HOB_TO_HOOD_COMMANDS 7
#define HOB_TO_HOOD_HASH_CODE_FAN_1 0xE3C01BE2
#define HOB_TO_HOOD_HASH_CODE_FAN_2 0xD051C301
#define HOB_TO_HOOD_HASH_CODE_FAN_3 0xC22FFFD7
#define HOB_TO_HOOD_HASH_CODE_FAN_4 0xB9121B29
#define HOB_TO_HOOD_HASH_CODE_FAN_OFF 0x55303A3
#define HOB_TO_HOOD_HASH_CODE_LIGHT_ON 0xE208293C
#define HOB_TO_HOOD_HASH_CODE_LIGHT_OFF 0x24ACF947
// based on https://pastebin.com/N6kG7Wu5
#define HOB_TO_HOOD_UNIT_MICROS 725
#define H2H_1 HOB_TO_HOOD_UNIT_MICROS
#define H2H_2 (HOB_TO_HOOD_UNIT_MICROS*2) // 1450
#define H2H_3 (HOB_TO_HOOD_UNIT_MICROS*3) // 2175
#define H2H_4 (HOB_TO_HOOD_UNIT_MICROS*4) // 2900
#define H2H_5 (HOB_TO_HOOD_UNIT_MICROS*5) // 3625
// First entry is the length of the raw command
const uint16_t Fan1[] PROGMEM { 15, H2H_2, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1,
H2H_3, H2H_1 };
const uint16_t Fan2[] PROGMEM { 9, H2H_2, H2H_2, H2H_1, H2H_4, H2H_1, H2H_3, H2H_5, H2H_3, H2H_3 };
const uint16_t Fan3[] PROGMEM { 9, H2H_1, H2H_3, H2H_4, H2H_4, H2H_3, H2H_1, H2H_1, H2H_3, H2H_3 };
const uint16_t Fan4[] PROGMEM { 13, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_2, H2H_1, H2H_3, H2H_1, H2H_1, H2H_2 };
const uint16_t FanOff[] PROGMEM { 15, H2H_1, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_2, H2H_3, H2H_1, H2H_2, H2H_1,
H2H_1, H2H_1 };
const uint16_t LightOn[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_4, H2H_1,
H2H_1, H2H_1, H2H_1, H2H_2 };
const uint16_t LightOff[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_1, H2H_1, H2H_3, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1,
H2H_2, H2H_1, H2H_1, H2H_1 };
const uint16_t *const Hob2HoodSendCommands[NUMBER_OF_HOB_TO_HOOD_COMMANDS] = { Fan1, Fan2, Fan3, Fan4, FanOff, LightOn, LightOff }; // Constant array in RAM
void setup() {
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
// Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.print(F("Ready to receive Hob2Hood IR signals at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send Hob2Hood IR signals at pin " STR(IR_SEND_PIN)));
}
/*
* Send Hob2Hood protocol
*/
void loop() {
static long sLastMillisOfSend = 0;
static uint8_t sSendCommandIndex = 0;
if (IrReceiver.decode()) {
IrReceiver.resume(); // Early enable receiving of the next IR frame
IrReceiver.printIRResultShort(&Serial);
/*
* Finally, check the received data and perform actions according to the received command
*/
switch (IrReceiver.decodedIRData.decodedRawData) {
case HOB_TO_HOOD_HASH_CODE_FAN_OFF:
Serial.print(F("FAN off"));
break;
case HOB_TO_HOOD_HASH_CODE_FAN_1:
Serial.print(F("FAN 1"));
break;
case HOB_TO_HOOD_HASH_CODE_FAN_2:
Serial.print(F("FAN 2"));
break;
default:
Serial.print(F("unknown Hob2Hood IR command"));
break;
}
}
/*
* Send next command every 5 seconds
*/
if (millis() - sLastMillisOfSend > 2000) {
sLastMillisOfSend = millis();
#if defined(__AVR__)
uint16_t tLengthOfRawCommand = pgm_read_word(Hob2HoodSendCommands[sSendCommandIndex]); // length is the 1. word in array
#else
uint16_t tLengthOfRawCommand = *Hob2HoodSendCommands[sSendCommandIndex]; // length is the 1. word in array
#endif
const uint16_t *tAddressOfRawCommandSequence = Hob2HoodSendCommands[sSendCommandIndex] + 1; // Raw sequence starts at the 2. word of array
Serial.print(F("Send Hob2Hood command index="));
Serial.println(sSendCommandIndex);
IrSender.sendRaw_P(tAddressOfRawCommandSequence, tLengthOfRawCommand, 38);
// Prepare for next command
sSendCommandIndex++;
if (sSendCommandIndex >= NUMBER_OF_HOB_TO_HOOD_COMMANDS) {
sSendCommandIndex = 0;
}
}
}

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -3,14 +3,14 @@
*
* Demonstrates receiving IR codes with the IRremote library and the use of the Arduino tone() function with this library.
* Long press of one IR button (receiving of multiple repeats for one command) is detected.
* If debug button is pressed (pin connected to ground) a long output is generated.
* If debug button is pressed (pin connected to ground) a long output is generated, which may disturb detecting of repeats.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2023 Armin Joachimsmeyer
* Copyright (c) 2020-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
@ -54,18 +54,14 @@
//#define DECODE_SONY
//#define DECODE_RC5
//#define DECODE_RC6
//#define DECODE_BOSEWAVE
//#define DECODE_LEGO_PF
//#define DECODE_MAGIQUEST
//#define DECODE_WHYNTER
//#define DECODE_FAST
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH // special decoder for all protocols
//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
// !!! Enabling B&O disables detection of Sony, because the repeat gap for SONY is smaller than the B&O frame gap :-( !!!
//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY!
@ -77,26 +73,26 @@
//
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 130 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@ -108,6 +104,8 @@
#define DEBUG_BUTTON_PIN 6
#endif
void generateTone();
void handleOverflow();
bool detectLongPress(uint16_t aLongPressDurationMillis);
void setup() {
@ -139,13 +137,16 @@ void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
Serial.println();
Serial.print(F("If you connect debug pin "));
if (digitalRead(DEBUG_BUTTON_PIN) != LOW) {
Serial.print(F("If you connect debug pin "));
# if defined(APPLICATION_PIN_STRING)
Serial.print(APPLICATION_PIN_STRING);
Serial.print(APPLICATION_PIN_STRING);
# else
Serial.print(DEBUG_BUTTON_PIN);
Serial.print(DEBUG_BUTTON_PIN);
# endif
Serial.println(F(" to ground, raw data is always printed"));
Serial.print(F(" to ground, "));
}
Serial.println(F("raw data is always printed"));
// infos for receive
Serial.print(RECORD_GAP_MICROS);
@ -153,7 +154,6 @@ void setup() {
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
#endif
}
void loop() {
@ -164,99 +164,61 @@ void loop() {
* E.g. command is in IrReceiver.decodedIRData.command
* address is in command is in IrReceiver.decodedIRData.address
* and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
*
* At 115200 baud, printing takes 40 ms for NEC protocol and 10 ms for NEC repeat
*/
if (IrReceiver.decode()) {
Serial.println();
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
#if FLASHEND < 0x3FFF //
// For less than 16k flash, only print a minimal summary of received data
IrReceiver.printIRResultMinimal(&Serial);
#else
/*
*
*/
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
# if !defined(ESP8266) && !defined(NRF5)
/*
* do double beep
*/
# if !defined(ESP32)
IrReceiver.stop(); // ESP32 uses another timer for tone()
# endif
tone(TONE_PIN, 1100, 10);
delay(50);
tone(TONE_PIN, 1100, 10);
delay(50);
# if !defined(ESP32)
IrReceiver.start(100000); // to compensate for 100 ms stop of receiver. This enables a correct gap measurement.
# endif
# endif
handleOverflow();
} else {
auto tStartMillis = millis();
# if !defined(ESP32)
IrReceiver.stop(); // ESP32 uses another timer for tone()
# endif
tone(TONE_PIN, 2200);
/*
* No overflow here.
* Stop receiver, generate a single beep, print short info and send usage and start receiver again
*****************************************************************************************************/
// No overflow, print a short summary of received data
# if defined(LOCAL_DEBUG)
IrReceiver.printIRResultShort(&Serial, true);
# else
IrReceiver.printIRResultShort(&Serial, true, digitalRead(DEBUG_BUTTON_PIN) == LOW);
# endif
// Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame
// so here we are 10 millis after end of frame. Sony20 has only a 12 ms repeat gap.
while ((millis() - tStartMillis) < 5)
;
noTone(TONE_PIN);
if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH)
&& (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN)
&& digitalRead(DEBUG_BUTTON_PIN) != LOW) {
/*
* For SONY the tone prevents the detection of a repeat after the 15 ms SONY gap.
* In debug mode and for unknown protocols, we need the time for extended output.
* Skipping tone will get exact gap time between transmissions and not running into repeat frames while wait for tone to end.
* This in turn enables the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value.
*/
generateTone();
}
# if !defined(ESP32)
// Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
# endif
IrReceiver.printIRSendUsage(&Serial);
# if defined(LOCAL_DEBUG)
IrReceiver.printIRResultRawFormatted(&Serial, true);
# else
/*
* Print info
*/
if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
// We have an unknown protocol, print more info
// We have debug enabled or an unknown protocol, print extended info
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
}
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
# endif
if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
/*
* The info output for a successful receive
*/
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
}
}
// tone on esp8266 works once, then it disables the successful IrReceiver.start() / timerConfigForReceive().
# if !defined(ESP8266) && !defined(NRF5) && !defined(LOCAL_DEBUG)
if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH)
&& (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN)
&& digitalRead(DEBUG_BUTTON_PIN) != LOW) {
/*
* If no debug mode or a valid protocol was received, play tone, wait and restore IR timer.
* For SONY the tone prevents the detection of a repeat
* Otherwise do not play a tone to get exact gap time between transmissions and not running into repeat frames while wait for tone to end.
* This will give the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value.
*/
# if !defined(ESP32)
IrReceiver.stop(); // ESP32 uses another timer for tone()
# endif
tone(TONE_PIN, 2200, 8);
# if !defined(ESP32)
delay(8);
IrReceiver.start(8000); // Restore IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
# endif
}
# endif
#else // #if FLASHEND >= 0x3FFF
// Print a minimal summary of received data
IrReceiver.printIRResultMinimal(&Serial);
#endif // #if FLASHEND >= 0x3FFF
/*
* !!!Important!!! Enable receiving of the next value,
* since receiving has stopped after the end of the current received data packet.
* !!!Important!!! Enable receiving of the next value, because receiving
* has stopped after the end of the current received data packet.
* Do it here, to preserve raw data for printing with printIRResultRawFormatted()
*/
IrReceiver.resume();
@ -271,7 +233,7 @@ void loop() {
}
}
// Check if the command was repeated for more than 1000 ms
// Check if repeats of the IR command was sent for more than 1000 ms
if (detectLongPress(1000)) {
Serial.print(F("Command 0x"));
Serial.print(IrReceiver.decodedIRData.command, HEX);
@ -289,10 +251,52 @@ void loop() {
}
/*
* Stop receiver, generate a single beep and start receiver again
*/
void generateTone() {
#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
# if defined(ESP32) // ESP32 uses another timer for tone()
tone(TONE_PIN, 2200, 5);
# else
IrReceiver.stopTimer(); // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too.
tone(TONE_PIN, 2200, 8);
delay(8);
IrReceiver.restartTimer(8000); // Restart IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
# endif
#endif
}
void handleOverflow() {
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
/*
* Stop timer, generate a double beep and start timer again
*/
# if defined(ESP32) // ESP32 uses another timer for tone()
tone(TONE_PIN, 1100, 10);
delay(50);
tone(TONE_PIN, 1100, 10);
# else
IrReceiver.stopTimer();
tone(TONE_PIN, 1100, 10);
delay(50);
tone(TONE_PIN, 1100, 10);
delay(50);
IrReceiver.restartTimer(100000); // to compensate for 100 ms stop of receiver. This enables a correct gap measurement.
# endif
#endif
}
unsigned long sMillisOfFirstReceive;
bool sLongPressJustDetected;
/**
* @return true once after the repeated command was received for longer than aLongPressDurationMillis milliseconds, false otherwise.
* True once we received the consecutive repeats for more than aLongPressDurationMillis milliseconds.
* The first frame, which is no repeat, is NOT counted for the duration!
* @return true once after the repeated IR command was received for longer than aLongPressDurationMillis milliseconds, false otherwise.
*/
bool detectLongPress(uint16_t aLongPressDurationMillis) {
if (!sLongPressJustDetected && (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) {

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -10,7 +10,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2022 Armin Joachimsmeyer
* Copyright (c) 2020-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -36,12 +36,13 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 600
# else
#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@ -56,7 +57,7 @@
*/
#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include <IRremote.hpp>
@ -86,8 +87,11 @@ void setup() {
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
Serial.print(MARK_EXCESS_MICROS);
Serial.println();
Serial.println(F("Because of the verbose output (>200 ms at 115200), repeats are probably not dumped correctly!"));
Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!"));
Serial.println();
Serial.println(F("If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2 or SamsungLG, which is determined by the repeats"));
Serial.println();
}
//+=============================================================================
@ -122,6 +126,7 @@ void loop() {
Serial.println(MARK_EXCESS_MICROS);
IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros
IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables
Serial.println(); // blank line between entries
IrReceiver.compensateAndPrintIRResultAsPronto(&Serial);
@ -144,6 +149,6 @@ void loop() {
// Serial.println(); // blank line between entries
// }
}
IrReceiver.resume(); // Prepare for the next value
IrReceiver.resume(); // Prepare for the next IR frame
}
}

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -123,7 +123,7 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
}
@ -190,7 +190,7 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
}
# if !defined(ESP32)
IrReceiver.stop(); // ESP32 uses another timer for tone()
IrReceiver.stopTimer(); // ESP32 uses another timer for tone()
# endif
if (millis() < tWaitTimeAfterBoot) {
// division by 1000 and printing requires much (8%) program memory
@ -218,7 +218,7 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
delay(200);
# if !defined(ESP32)
IrReceiver.start(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement.
IrReceiver.restartTimer(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement.
# endif
Serial.println(F("Wait for \"not supported\" to disappear"));

View File

@ -33,8 +33,8 @@
#include <Arduino.h>
#define IR_INPUT_PIN 2
//#define IR_INPUT_PIN 3
#define IR_RECEIVE_PIN 2
//#define IR_RECEIVE_PIN 3
/*
* Helper macro for getting a macro definition as string
@ -55,19 +55,19 @@ void setup()
Serial.println(F("START " __FILE__ " from " __DATE__));
#if defined(EICRA) && defined(EIFR) && defined(EIMSK)
# if (IR_INPUT_PIN == 2)
# if (IR_RECEIVE_PIN == 2)
EICRA |= _BV(ISC00); // interrupt on any logical change
EIFR |= _BV(INTF0); // clear interrupt bit
EIMSK |= _BV(INT0); // enable interrupt on next change
# elif (IR_INPUT_PIN == 3)
# elif (IR_RECEIVE_PIN == 3)
EICRA |= _BV(ISC10); // enable interrupt on pin3 on both edges for ATmega328
EIFR |= _BV(INTF1); // clear interrupt bit
EIMSK |= _BV(INT1); // enable interrupt on next change
# endif
#else
attachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN), measureTimingISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE);
#endif
Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_INPUT_PIN)));
Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN)));
Serial.println();
}
@ -197,9 +197,9 @@ void loop()
void IRAM_ATTR measureTimingISR()
#else
# if defined(EICRA) && defined(EIFR) && defined(EIMSK)
# if (IR_INPUT_PIN == 2)
# if (IR_RECEIVE_PIN == 2)
ISR(INT0_vect)
# elif (IR_INPUT_PIN == 3)
# elif (IR_RECEIVE_PIN == 3)
ISR(INT1_vect)
# endif
# else
@ -213,7 +213,7 @@ void measureTimingISR()
/*
* read level and give feedback
*/
uint8_t tInputLevel = digitalRead(IR_INPUT_PIN);
uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN);
digitalWrite(LED_BUILTIN, !tInputLevel);
if (tMicrosDelta > 10000)

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -39,7 +39,7 @@
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -65,7 +65,7 @@ void setup() {
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -33,7 +33,9 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>
@ -96,6 +98,10 @@
//#define BOSE_CMD_ALARM_ON_OFF 0x22
//#define BOSE_CMD_ALARM_WAKE_TO 0x70
//#define BOSE_CMD_ALARM_TIME 0x23
// Different last 3 codes for Wave Sound Touch IV
//#define BOSE_CMD_ALARM_1 0x22
//#define BOSE_CMD_ALARM_2 0x62
//#define BOSE_CMD_ALARM_SETUP 0xA2
bool sPrintMenu;
void printMenu();
@ -111,11 +117,15 @@ void setup() {
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin 3"));
uint8_t tSendPin = 3;
IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
Serial.println(tSendPin);
#endif
sPrintMenu = true;

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -34,14 +34,17 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
//#define USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN // Simulate an active high receiver signal instead of an active low signal.
//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
//#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory
//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
#include <IRremote.hpp>
#define DELAY_AFTER_SEND 2000
@ -57,15 +60,21 @@ void setup() {
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
// disableLEDFeedback(); // Disable feedback LED at default feedback LED pin
# if defined(IR_SEND_PIN_STRING)
Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
# endif
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin 3"));
// Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN
uint8_t tSendPin = 3;
IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
Serial.println(tSendPin);
#endif
#if !defined(SEND_PWM_BY_TIMER)
@ -125,7 +134,7 @@ void loop() {
delay(DELAY_AFTER_SEND);
if (sRepeats == 0) {
#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
#if FLASHEND >= 0x3FFF && ((defined(RAMEND) && RAMEND > 0x6FF) || (defined(RAMSIZE) && RAMSIZE > 0x6FF)) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
/*
* Send constant values only once in this demo
*/
@ -165,6 +174,7 @@ void loop() {
/*
* With Send sendNECMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte.
* Use bitreverse32Bit().
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
@ -326,7 +336,7 @@ void loop() {
IrSender.sendRC6(sAddress, sCommand, sRepeats, true);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
#if FLASHEND >= 0x3FFF && ((defined(RAMEND) && RAMEND > 0x4FF) || (defined(RAMSIZE) && RAMSIZE > 0x4FF)) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
/*
* Next example how to use the IrSender.write function
*/
@ -336,6 +346,9 @@ void loop() {
IRSendData.command = sCommand;
IRSendData.flags = IRDATA_FLAGS_EMPTY;
Serial.println(F("Send next protocols with IrSender.write"));
Serial.flush();
IRSendData.protocol = SAMSUNG;
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -42,7 +42,9 @@
//#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol
#define NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU 5
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
#define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver.
//#define DEBUG // Activate this for more output from the LG-AC driver.
@ -75,7 +77,7 @@ delay(4000); // To be able to connect Serial monitor after reset or power up and
/*
* The IR library setup. That's all!
*/
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println();

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -32,7 +32,9 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>
@ -64,7 +66,7 @@ void setup() {
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
}
void loop() {

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -37,7 +37,9 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -58,7 +60,7 @@ void setup() {
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
}
/*

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -1,7 +1,8 @@
/*
* SimpleReceiver.cpp
*
* Demonstrates receiving NEC IR codes with IRremote
* Demonstrates receiving ONLY NEC protocol IR codes with IRremote
* If no protocol is defined, all protocols (except Bang&Olufsen) are active.
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@ -40,7 +41,7 @@
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
//#define DECODE_LG
#define DECODE_NEC // Includes Apple and Onkyo
#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
@ -94,23 +95,20 @@ void loop() {
if (IrReceiver.decode()) {
/*
* Print a short summary of received data
* Print a summary of received data
*/
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
// We have an unknown protocol here, print more info
// We have an unknown protocol here, print extended info
IrReceiver.printIRResultRawFormatted(&Serial, true);
IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
} else {
IrReceiver.resume(); // Early enable receiving of the next IR frame
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
}
Serial.println();
/*
* !!!Important!!! Enable receiving of the next value,
* since receiving has stopped after the end of the current received data packet.
*/
IrReceiver.resume(); // Enable receiving of the next value
/*
* Finally, check the received data and perform actions according to the received command
*/

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -85,7 +85,7 @@ void setup() {
IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler);
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols (&Serial);
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
}
@ -94,9 +94,7 @@ void loop() {
* Print in loop (interrupts are enabled here) if received data is available.
*/
if (sIRDataJustReceived) {
// Print a short summary of received data
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
// Print a summary of received data
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
/*
@ -105,6 +103,9 @@ void loop() {
* and the the first mark of the next (repeat) data was yet received
*/
IrReceiver.printIRResultRawFormatted(&Serial, true); //
} else {
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
}
Serial.println();
}
@ -124,6 +125,10 @@ IRAM_ATTR
# endif
void ReceiveCompleteCallbackHandler() {
IrReceiver.decode(); // fill IrReceiver.decodedIRData
/*
* Enable receiving of the next value.
*/
IrReceiver.resume();
/*
* Check the received data and perform actions according to the received command
@ -146,13 +151,4 @@ void ReceiveCompleteCallbackHandler() {
*/
sIRDataJustReceived = true;
/*
* Enable receiving of the next value.
* !!!Attention!!!
* After receiving the first mark of the next (repeat) data, 3 variables required for printing are reset/overwritten.
* - IrReceiver.irparams.rawlen
* - IrReceiver.irparams.rawbuf[0]
* - IrReceiver.irparams.OverflowFlag)
*/
IrReceiver.resume();
}

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -13,7 +13,9 @@
*/
#include <Arduino.h>
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
@ -36,8 +38,8 @@ void setup() {
/*
* The IR library setup. That's all!
*/
// IrSender.begin(); // Start with IR_SEND_PIN as send pin and if NO_LED_FEEDBACK_CODE is NOT defined, enable feedback LED at default feedback LED pin
IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin and disable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
disableLEDFeedback(); // Disable feedback LED at default feedback LED pin
}
/*
@ -66,6 +68,18 @@ void loop() {
// Receiver output for the first loop must be: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
IrSender.sendNEC(0x00, sCommand, sRepeats);
/*
* If you want to send a raw HEX value directly like e.g. 0xCB340102 you must use sendNECRaw()
*/
// Serial.println(F("Send 32 bit LSB 0xCB340102 with NECRaw()"));
// IrSender.sendNECRaw(0xCB340102, sRepeats);
/*
* If you want to send an "old" MSB HEX value used by IRremote versions before 3.0 like e.g. 0x40802CD3 you must use sendNECMSB()
*/
// Serial.println(F("Send old 32 bit MSB 0x40802CD3 with sendNECMSB()"));
// IrSender.sendNECMSB(0x40802CD3, 32, sRepeats);
/*
* Increment send values
*/

View File

@ -0,0 +1,341 @@
/*
* 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-2023 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 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
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
#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
# 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__) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
#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__) // 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#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__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA1 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
#define APPLICATION_PIN PIN_PB2 // 5
#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
# elif defined(__AVR_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(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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
// tone() is included in ESP32 core since 2.0.2
#if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
#endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_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
#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) // !!!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)
#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
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids 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
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif

View File

@ -26,7 +26,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2023 Armin Joachimsmeyer
* Copyright (c) 2022-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -50,49 +50,26 @@
#include <Arduino.h>
/*
* Set sensible receive pin for different CPU's
*/
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
/*
* This program runs on 1 MHz CPU clock :-) and is requires only 1550 bytes program memory using ATTiny core
*/
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut" - Saves up to 700 bytes program memory and 70 bytes RAM for ATtinyCore
# if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
# else
#define IR_RECEIVE_PIN 0 // PCINT0
# endif
#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IR_RECEIVE_PIN 10
#elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#define IR_RECEIVE_PIN 21 // INT0
#elif defined(ESP8266)
#define IR_RECEIVE_PIN 14 // D5
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_RECEIVE_PIN 8
#elif defined(ESP32)
#define IR_RECEIVE_PIN 15
#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO)
#define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#else
#define IR_RECEIVE_PIN 2 // INT0
//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.
#endif
#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
/*
* Second: include the code and compile it.
* Protocol selection
*/
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
#include "TinyIRReceiver.hpp"
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
/*
* 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 fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // include the code
/*
* Helper macro for getting a macro definition as string
@ -102,8 +79,6 @@
#define STR(x) STR_HELPER(x)
#endif
volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
void setup() {
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217)
@ -127,21 +102,24 @@ void setup() {
}
void loop() {
if (sCallbackData.justWritten) {
sCallbackData.justWritten = false;
#if defined(USE_FAST_PROTOCOL)
Serial.print(F("Command=0x"));
#else
if (TinyIRReceiverData.justWritten) {
TinyIRReceiverData.justWritten = false;
#if !defined(USE_FAST_PROTOCOL)
// We have no address at FAST protocol
Serial.print(F("Address=0x"));
Serial.print(sCallbackData.Address, HEX);
Serial.print(F(" Command=0x"));
Serial.print(TinyIRReceiverData.Address, HEX);
Serial.print(' ');
#endif
Serial.print(sCallbackData.Command, HEX);
if (sCallbackData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F("Command=0x"));
Serial.print(TinyIRReceiverData.Command, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F(" Repeat"));
}
if (sCallbackData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
Serial.print(F(" Parity failed"));
#if !defined(USE_EXTENDED_NEC_PROTOCOL) && !defined(USE_ONKYO_PROTOCOL)
Serial.print(F(", try USE_EXTENDED_NEC_PROTOCOL or USE_ONKYO_PROTOCOL"));
#endif
}
Serial.println();
}
@ -151,40 +129,30 @@ void loop() {
}
/*
* This is the function, which is called if a complete command was received
* 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
* It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here
*/
#if defined(ESP8266) || defined(ESP32)
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
#if defined(USE_FAST_PROTOCOL)
void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags)
#elif defined(USE_ONKYO_PROTOCOL)
void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags)
#else
void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags)
#endif
{
#if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
// Copy data for main loop, this is the recommended way for handling a callback :-)
# if !defined(USE_FAST_PROTOCOL)
sCallbackData.Address = aAddress;
# endif
sCallbackData.Command = aCommand;
sCallbackData.Flags = aFlags;
sCallbackData.justWritten = true;
#else
void handleReceivedTinyIRData() {
# if defined(ARDUINO_ARCH_MBED) || defined(ESP32)
/*
* Printing is not allowed in ISR context for any kind of RTOS
* Printing is not allowed in ISR context for any kind of RTOS, so we use the slihjtly more complex,
* but recommended way for handling a callback :-). Copy data for main loop.
* For Mbed we get a kernel panic and "Error Message: Semaphore: 0x0, Not allowed in ISR context" for Serial.print()
* for ESP32 we get a "Guru Meditation Error: Core 1 panic'ed" (we also have an RTOS running!)
*/
// Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
# if defined(USE_FAST_PROTOCOL)
printTinyReceiverResultMinimal(&Serial, aCommand, aFlags);
// Do something useful here...
# else
printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags);
// As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
printTinyReceiverResultMinimal(&Serial);
# endif
#endif
}
#endif

View File

@ -0,0 +1,341 @@
/*
* 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-2023 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
* Arduino-IRremote is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*
*/
/*
* Pin mapping table for different platforms
*
* Platform IR input IR output Tone Core/Pin schema
* --------------------------------------------------------------
* DEFAULT/AVR 2 3 4 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
* ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
#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
# 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__) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
#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__) // 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#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__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
#define IR_SEND_PIN PIN_PA1 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here.
#define IR_SEND_PIN PIN_PA7 // 3
#define APPLICATION_PIN PIN_PB2 // 5
#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone()
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
# elif defined(__AVR_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(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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
// tone() is included in ESP32 core since 2.0.2
#if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
#endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
delay(aDuration);
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define IR_RECEIVE_PIN 15 // D15
#define IR_SEND_PIN 4 // D4
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_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
#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) // !!!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)
#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
#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 / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#define _IR_TIMING_TEST_PIN 7
#endif // defined(ESP8266)
#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids 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
/*
* Helper macro for getting a macro definition as string
*/
#if !defined(STR_HELPER)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif

View File

@ -1,10 +1,12 @@
/*
* TinySender.cpp
*
* Example for sending FAST or NEC protocol using TinyIR.
* Example for sending using TinyIR. By default sends simultaneously using all supported protocols
* To use a single protocol, simply delete or comment out all unneeded protocols in the main loop
* Program size is significantly reduced when using a single protocol
* For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender,
* which does the same, but uses the IRRemote library (and is therefore much more flexible).
*
* NEC protocol codes are sent in standard format with 8bit address and 8 bit command as in SimpleSender example.
* Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible).
*
* The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header.
* FAST Protocol characteristics:
@ -21,7 +23,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2023 Armin Joachimsmeyer
* Copyright (c) 2022-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -44,16 +46,10 @@
*/
#include <Arduino.h>
//#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's
#include "TinyIRSender.hpp"
#define IR_SEND_PIN 3
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
@ -82,29 +78,47 @@ void loop() {
*/
Serial.println();
Serial.print(F("Send now:"));
#if defined(USE_FAST_PROTOCOL)
Serial.print(F(" address=0x"));
Serial.print(sAddress, HEX);
#endif
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
Serial.print(F(" repeats="));
Serial.print(sRepeats);
Serial.println();
#if defined(USE_FAST_PROTOCOL)
Serial.println(F("Send FAST with 8 bit address"));
// Send with FAST
// No address and only 16 bits of data, interpreted as 8 bit command and 8 bit inverted command for parity checking
Serial.println(F("Send FAST with 8 bit command"));
Serial.flush();
sendFAST(IR_SEND_PIN, sCommand, sRepeats);
#elif defined(USE_ONKYO_PROTOCOL)
// Send with NEC
// NEC uses 8 bit address and 8 bit command each with 8 bit inverted parity checks
// However, sendNEC will accept 16 bit address and commands too (but remove the parity checks)
Serial.println(F("Send NEC with 8 bit address and command"));
Serial.flush();
sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats);
// Send with Extended NEC
// Like NEC, but the address is forced 16 bits with no parity check
Serial.println(F("Send ExtendedNEC with 16 bit address and 8 bit command"));
Serial.flush();
sendExtendedNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats);
// Send with ONKYO
// Like NEC, but both the address and command are forced 16 bits with no parity check
Serial.println(F("Send ONKYO with 16 bit address and command"));
Serial.flush();
sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats);
#else
Serial.println(F("Send NEC with 8 bit address"));
// Send with NEC2
// Instead of sending the NEC special repeat code, sends the full original frame for repeats
// Sending NEC2 is done by setting the optional bool NEC2Repeats argument to true (defaults to false)
// sendExtendedNEC and sendONKYO also support the NEC2Repeats argument for full frame repeats (not demonstrated here)
Serial.println(F("Send NEC2 with 8 bit address and command and original frame repeats"));
Serial.flush();
sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats);
#endif
sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true);
/*
* Increment send values
* Also increment address just for demonstration, which normally makes no sense

View File

@ -41,8 +41,9 @@
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
* SAMD21 3 4 5
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
* BluePill PA6 PA7 PA3
* ESP32 15 4 27
* ESP32-C3 6 7 10
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
*/
@ -90,14 +91,14 @@
# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/
// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/
#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32
// 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 // use 18 instead of PIN_PA1 for TinyCore32
#define IR_SEND_PIN PIN_PA2 // 19
#define TONE_PIN PIN_PA3 // 20
#define APPLICATION_PIN PIN_PA0 // 0
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
@ -173,11 +174,12 @@
#define noTone(a) void()
#define TONE_PIN 42 // Dummy for examples using it
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
#define IR_INPUT_PIN 8
#define IR_SEND_PIN 9
#define TONE_PIN 10 // ADC2_0
#define APPLICATION_PIN 11
#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 IR_RECEIVE_PIN 6
#define IR_SEND_PIN 7
#define TONE_PIN 10
#define APPLICATION_PIN 18
#elif defined(ESP32)
#include <Arduino.h>
@ -322,19 +324,13 @@ void noTone(uint8_t aPinNumber){
#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation
#else
# if defined(SEND_PWM_BY_TIMER)
#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp
#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 0xFFFF // Dummy value for platforms where RAMEND is not defined
#endif
#if !defined (RAMSIZE)
#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined
#endif
/*
* Helper macro for getting a macro definition as string

View File

@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2023 Armin Joachimsmeyer
* Copyright (c) 2020-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -36,12 +36,13 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF
//#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF
#define RAW_BUFFER_LENGTH 150 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 180
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
#define RAW_BUFFER_LENGTH 200 // 600 is too much here, because then variables are overwritten. 500 is OK without Pronto and 200 is OK with Pronto
# else
#define RAW_BUFFER_LENGTH 200 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100.
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@ -55,6 +56,8 @@
// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
//#define TRACE // For internal usage
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@ -80,9 +83,9 @@
#define DECODE_LG
#define DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here.
//#define ENABLE_BEO_WITHOUT_FRAME_GAP // For successful unit testing we must see the warning at ir_BangOlufsen.hpp:88:2
//#define ENABLE_BEO_WITHOUT_FRAME_GAP // !!!For successful unit testing we must see the warning at ir_BangOlufsen.hpp:100:2!!!
#if defined(DECODE_BEO)
#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer
#define RECORD_GAP_MICROS 16000 // Force to get the complete frame including the 3. space of 15 ms in the receive buffer
#define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz here (instead of 455 kHz).
#endif
@ -93,6 +96,7 @@
#define DECODE_FAST
#endif
//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
#include <IRremote.hpp>
#if defined(APPLICATION_PIN)
@ -136,16 +140,24 @@ void setup() {
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#endif
Serial.println(F("Use ReceiveCompleteCallback"));
Serial.println(F("Receive buffer length is " STR(RAW_BUFFER_LENGTH)));
#if defined(IR_SEND_PIN)
IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
# if defined(IR_SEND_PIN_STRING)
Serial.println(F("at pin " IR_SEND_PIN_STRING));
Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
# endif
#else
IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
Serial.println(F("Send IR signals at pin 3"));
// Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN
uint8_t tSendPin = 3;
IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
Serial.println(tSendPin);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
@ -273,7 +285,7 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
/*
* Test callback function
* Has the same functionality as available()
* Has the same functionality as a check with available()
*/
void ReceiveCompleteCallbackHandler() {
sDataJustReceived = true;
@ -281,8 +293,15 @@ void ReceiveCompleteCallbackHandler() {
void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
// wait until signal has received
uint16_t tTimeoutCounter = 1000; // gives 10 seconds timeout
while (!sDataJustReceived) {
};
delay(10);
if (tTimeoutCounter == 0) {
Serial.println(F("Receive timeout happened"));
break;
}
tTimeoutCounter--;
}
sDataJustReceived = false;
if (IrReceiver.decode()) {
@ -305,6 +324,8 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
IrReceiver.resume(); // Early resume
if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
Serial.println(F("ERROR: Unknown protocol"));
} else {
@ -328,9 +349,9 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
}
}
IrReceiver.resume();
} else {
Serial.println(F("No data received"));
IrReceiver.resume();
}
Serial.println();
}
@ -344,7 +365,7 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
uint16_t sAddress = 0xFFF1;
uint8_t sCommand = 0x76;
uint16_t s16BitCommand = 0x9876;
#define sRepeats 0 // no unit test for repeats
uint8_t sRepeats = 0;
void loop() {
/*
@ -360,31 +381,42 @@ void loop() {
Serial.println(F("Send NEC with 8 bit address"));
Serial.flush();
IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats);
IrSender.sendNEC(sAddress & 0xFF, sCommand, 0);
checkReceive(sAddress & 0xFF, sCommand);
//
for (int8_t i = 0; i < sRepeats; i++) {
Serial.println(F("Repeat NEC frame for NEC2"));
Serial.flush();
// if debug is enabled, printing time (50 ms) is too high anyway
delayMicroseconds(NEC_REPEAT_DISTANCE - 200); // 200 is just a guess
IrSender.sendNEC(sAddress & 0xFF, sCommand, 0);
checkReceive(sAddress & 0xFF, sCommand);
}
delay(DELAY_AFTER_SEND); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
Serial.println(F("Send NEC with 16 bit address"));
Serial.flush();
IrSender.sendNEC(sAddress, sCommand, sRepeats);
IrSender.sendNEC(sAddress, sCommand, 0);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC2 with 16 bit address"));
Serial.flush();
IrSender.sendNEC2(sAddress, sCommand, sRepeats);
IrSender.sendNEC2(sAddress, sCommand, 0);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
if (sAddress == 0xFFF1) {
# if FLASHEND >= 0x7FFF // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc.
# if FLASHEND >= 0x7FFF && ((defined(RAMEND) && RAMEND <= 0x6FF) || (defined(RAMSIZE) && RAMSIZE < 0x6FF)) // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc.
/*
* Send constant values only once in this demo
*/
Serial.println(F("Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
Serial.flush();
// This is copied to stack/ram internally
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
"0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */
"0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */
@ -412,13 +444,14 @@ void loop() {
*/
Serial.println(F("Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)"));
Serial.flush();
IrSender.sendNECRaw(0x03040102, sRepeats);
IrSender.sendNECRaw(0x03040102, 0);
checkReceive(0x0102, 0x304);
delay(DELAY_AFTER_SEND);
/*
* With Send sendNECMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte.
* Use bitreverse32Bit().
* Example:
* 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3
*/
@ -446,7 +479,7 @@ void loop() {
* Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first
*/
Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance"));
Serial.println(F(" LSB first"));
Serial.println(F("-LSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST, 0,
@ -460,7 +493,7 @@ void loop() {
delay(DELAY_AFTER_SEND);
// The same with MSB first. Use bit reversed raw data of LSB first part
Serial.println(F(" MSB first"));
Serial.println(F("-MSB first"));
# if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
@ -578,32 +611,32 @@ void loop() {
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
Serial.flush();
IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, sRepeats);
IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, 0);
checkReceive(sAddress, (sCommand + 1) << 8 | sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Apple"));
Serial.flush();
IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
IrSender.sendApple(sAddress & 0xFF, sCommand, 0);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
Serial.println(F("Send Panasonic"));
Serial.flush();
IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats);
IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, 0);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID"));
Serial.flush();
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, 0, 0x4711);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo_Denon variant"));
Serial.flush();
IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, sRepeats);
IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, 0);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
#endif
@ -611,13 +644,13 @@ void loop() {
#if defined(DECODE_DENON)
Serial.println(F("Send Denon"));
Serial.flush();
IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
IrSender.sendDenon(sAddress & 0x1F, sCommand, 0);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Denon/Sharp variant"));
Serial.flush();
IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
IrSender.sendSharp(sAddress & 0x1F, sCommand, 0);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
#endif
@ -625,39 +658,39 @@ void loop() {
#if defined(DECODE_SONY)
Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1F, sCommand, sRepeats);
IrSender.sendSony(sAddress & 0x1F, sCommand, 0);
checkReceive(sAddress & 0x1F, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 8 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL);
IrSender.sendSony(sAddress & 0xFF, sCommand, 0, SIRCS_15_PROTOCOL);
checkReceive(sAddress & 0xFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL);
IrSender.sendSony(sAddress & 0x1FFF, sCommand, 0, SIRCS_20_PROTOCOL);
checkReceive(sAddress & 0x1FFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_SAMSUNG)
Serial.println(F("Send Samsung 8 bit command"));
Serial.println(F("Send Samsung 8 bit command and 8 bit address"));
Serial.flush();
IrSender.sendSamsung(sAddress, sCommand, sRepeats);
checkReceive(sAddress, sCommand);
IrSender.sendSamsung(sAddress & 0xFF, sCommand, 0);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Samsung 16 bit command"));
Serial.println(F("Send Samsung 16 bit command and address"));
Serial.flush();
IrSender.sendSamsung(sAddress, s16BitCommand, sRepeats);
IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, 0);
checkReceive(sAddress, s16BitCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Samsung48 16 bit command"));
Serial.flush();
IrSender.sendSamsung48(sAddress, s16BitCommand, sRepeats);
IrSender.sendSamsung48(sAddress, s16BitCommand, 0);
checkReceive(sAddress, s16BitCommand);
delay(DELAY_AFTER_SEND);
#endif
@ -665,13 +698,13 @@ void loop() {
#if defined(DECODE_RC5)
Serial.println(F("Send RC5"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits
IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, 0, true); // 5 address, 6 command bits
checkReceive(sAddress & 0x1F, sCommand & 0x3F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5X with 7.th MSB of command set"));
Serial.flush();
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, 0, true); // 5 address, 7 command bits
checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40);
delay(DELAY_AFTER_SEND);
#endif
@ -680,7 +713,7 @@ void loop() {
Serial.println(F("Send RC6"));
// RC6 check does not work stable without the flush
Serial.flush();
IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true);
IrSender.sendRC6(sAddress & 0xFF, sCommand, 0, true);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
#endif
@ -699,7 +732,7 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
IrSender.write(&IRSendData, 0);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif
@ -713,8 +746,8 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
checkReceive(IRSendData.address, IRSendData.command);
IrSender.write(&IRSendData, 0);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif
@ -723,7 +756,7 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
IrSender.write(&IRSendData, 0);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif
@ -739,19 +772,25 @@ void loop() {
#if defined(DECODE_BEO)
Serial.println(F("Send Bang&Olufsen"));
Serial.flush();
IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, sRepeats);
IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0);
# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
delay((RECORD_GAP_MICROS / 1000) + 1);
Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled"));
Serial.println(F("- Now print raw data and try to decode it, which must fail!"));
IrReceiver.printIRResultRawFormatted(&Serial, true);
uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen;
IrReceiver.decodedIRData.rawDataPtr->rawlen = 6;
uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawlen;
IrReceiver.decodedIRData.rawlen = 6;
// decode first part of frame
IrReceiver.decode();
IrReceiver.printIRResultShort(&Serial);
// Remove trailing 6 entries for next decode
IrReceiver.decodedIRData.rawDataPtr->rawlen = tOriginalRawlen - 6;
for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawDataPtr->rawlen; ++i) {
// Remove trailing 6 entries for second decode try
Serial.println();
Serial.println(
F(
"- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode"));
IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6;
for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) {
IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6];
}
# endif
@ -763,7 +802,7 @@ void loop() {
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
IrSender.write(&IRSendData, 0);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif
@ -773,7 +812,7 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
IrSender.write(&IRSendData, sRepeats);
IrSender.write(&IRSendData, 0);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif
@ -806,7 +845,11 @@ void loop() {
sAddress += 0x0101;
sCommand += 0x11;
s16BitCommand += 0x1111;
sRepeats++;
// clip repeats at 4
if (sRepeats > 4) {
sRepeats = 4;
}
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
}

View File

@ -1,6 +1,8 @@
START ../src/UnitTest.cpp from Feb 22 2023
Using library version 4.1.0
Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2
Use ReceiveCompleteCallback
Receive buffer length is 200
Send IR signals at pin 3
If you connect debug pin 5 to ground, raw data is always printed
Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us
@ -12,7 +14,7 @@ address=0xFFF1 command=0x76
Send NEC with 8 bit address
Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
Send with: IrSender.sendNEC(0xF1, 0x76, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1044300
+8950,-4400
+ 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
@ -29,7 +31,7 @@ Sum: 67650
Send NEC with 16 bit address
Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
Send with: IrSender.sendNEC(0xFFF1, 0x76, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1055100
+8850,-4450
+ 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
@ -46,7 +48,7 @@ Sum: 73150
Send NEC2 with 16 bit address
Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
Send with: IrSender.sendNEC(0xFFF1, 0x76, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1055500
+8950,-4400
+ 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500
@ -63,7 +65,7 @@ Sum: 73400
Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats
Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
Send with: IrSender.sendNEC(0x80, 0x45, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1064450
+9050,-4450
+ 550,- 550 + 600,- 550 + 600,- 600 + 550,- 600
@ -80,7 +82,7 @@ Sum: 67800
Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)
Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first
Send with: IrSender.sendNEC(0x4, 0x8, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1061400
+9000,-4400
+ 600,- 500 + 650,- 500 + 600,-1650 + 600,- 500
@ -97,7 +99,7 @@ Sum: 67900
Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)
Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
Send with: IrSender.sendOnkyo(0x102, 0x304, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1059700
+8900,-4400
+ 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500
@ -114,7 +116,7 @@ Sum: 55450
Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3)
Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
Send with: IrSender.sendNEC(0x102, 0x34, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1061500
+8950,-4400
+ 600,- 500 + 550,-1700 + 600,- 500 + 650,- 500
@ -131,7 +133,7 @@ Sum: 61000
Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants
Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
rawData[100]:
rawData[100]:
-1059500
+3450,-1700
+ 450,- 450 + 450,-1250 + 450,- 400 + 450,- 450
@ -150,10 +152,10 @@ rawData[100]:
Sum: 54100
Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance
LSB first
- LSB first
Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
rawData[100]:
rawData[100]:
-1076450
+3450,-1700
+ 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
@ -171,10 +173,10 @@ rawData[100]:
+ 400
Sum: 53200
MSB first
- MSB first
Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
Send with: IrSender.sendPanasonic(0xB, 0x10, <numberOfRepeats>);
rawData[100]:
rawData[100]:
-1070700
+3400,-1700
+ 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400
@ -194,10 +196,10 @@ Sum: 53150
Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first
Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
Send with:
Send on a 8 bit platform with:
uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1650, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
rawData[148]:
rawData[148]:
-1076300
+8850,-4400
+ 600,-1650 + 550,- 600 + 550,- 600 + 550,- 600
@ -223,10 +225,10 @@ Sum: 138200
Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first
Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first
Send with:
Send on a 8 bit platform with:
uint32_t tRawData[]={0x87654321, 0xDCBA9};
IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
rawData[106]:
rawData[106]:
-1115100
+ 350,- 600
+ 650,- 250 + 350,- 550 + 350,- 550 + 300,- 600
@ -246,8 +248,8 @@ Sum: 47550
Send generic 32 bit PulseWidth 0x87654321 LSB first
Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
Send with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
rawData[66]:
Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
rawData[66]:
-1088600
+ 950,- 550
+ 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250
@ -263,7 +265,7 @@ Sum: 24500
Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first
Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, <numberOfRepeats>);
rawData[112]:
rawData[112]:
-1089000
+ 350,- 800 + 350,- 800 + 350,- 800 + 300,- 850
+ 300,- 850 + 300,- 850 + 300,- 850 + 350,- 800
@ -284,7 +286,7 @@ Sum: 63850
Send Onkyo (NEC with 16 bit command)
Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first
Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1070700
+8900,-4550
+ 500,-1600 + 650,- 500 + 600,- 500 + 600,- 550
@ -301,7 +303,7 @@ Sum: 76500
Send Apple
Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first
Send with: IrSender.sendApple(0xF1, 0x76, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1054650
+8950,-4400
+ 600,- 550 + 550,-1650 + 650,-1600 + 600,-1600
@ -318,7 +320,7 @@ Sum: 72100
Send Panasonic
Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
Send with: IrSender.sendPanasonic(0xFF1, 0x76, <numberOfRepeats>);
rawData[100]:
rawData[100]:
-1054300
+3450,-1700
+ 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450
@ -339,7 +341,7 @@ Sum: 64400
Send Kaseikyo with 0x4711 as Vendor ID
Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first
Send with: IrSender.sendKaseikyo(0xFF1, 0x76, <numberOfRepeats>, 0x4711);
rawData[100]:
rawData[100]:
-1074550
+3400,-1750
+ 450,-1250 + 450,- 450 + 450,- 400 + 450,- 450
@ -360,7 +362,7 @@ Sum: 69500
Send Kaseikyo_Denon variant
Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, <numberOfRepeats>);
rawData[100]:
rawData[100]:
-1067700
+3400,-1750
+ 450,- 400 + 450,- 450 + 450,-1250 + 450,- 400
@ -381,7 +383,7 @@ Sum: 67700
Send Denon
Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first
Send with: IrSender.sendDenon(0x11, 0x76, <numberOfRepeats>);
rawData[32]:
rawData[32]:
-1073050
+ 250,-1850 + 250,- 750 + 250,- 800 + 250,- 800
+ 250,-1800 + 250,- 800 + 250,-1800 + 250,-1850
@ -392,7 +394,7 @@ Sum: 23050
Send Denon/Sharp variant
Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first
Send with: IrSender.sendSharp(0x11, 0x76, <numberOfRepeats>);
rawData[32]:
rawData[32]:
-1018750
+ 300,-1750 + 300,- 750 + 250,- 800 + 250,- 800
+ 250,-1800 + 250,- 800 + 250,-1800 + 300,-1800
@ -403,7 +405,7 @@ Sum: 24100
Send Sony/SIRCS with 7 command and 5 address bits
Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
rawData[26]:
rawData[26]:
-1020950
+2400,- 650
+ 550,- 600 +1200,- 550 +1250,- 550 + 650,- 550
@ -414,7 +416,7 @@ Sum: 20950
Send Sony/SIRCS with 7 command and 8 address bits
Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first
Send with: IrSender.sendSony(0xF1, 0x76, 2, 15);
rawData[32]:
rawData[32]:
-1032550
+2400,- 600
+ 600,- 600 +1200,- 600 +1200,- 550 + 650,- 550
@ -426,7 +428,7 @@ Sum: 26400
Send Sony/SIRCS with 7 command and 13 address bits
Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first
Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20);
rawData[42]:
rawData[42]:
-1036350
+2300,- 650
+ 600,- 600 +1200,- 550 +1250,- 550 + 650,- 600
@ -436,65 +438,65 @@ rawData[42]:
+1200,- 550 +1200,- 600 +1250,- 600 +1200
Sum: 35350
Send Samsung 8 bit command
Protocol=Samsung Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
Send with: IrSender.sendSamsung(0xFFF1, 0x76, <numberOfRepeats>);
rawData[68]:
-1039650
+4400,-4450
+ 550,-1700 + 550,- 550 + 600,- 550 + 550,- 550
+ 600,-1650 + 550,-1650 + 600,-1650 + 550,-1650
+ 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650
+ 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
+ 600,- 550 + 550,-1650 + 600,-1650 + 600,- 550
+ 550,-1650 + 600,-1650 + 550,-1700 + 550,- 550
+ 600,-1650 + 550,- 550 + 600,- 550 + 600,-1600
+ 600,- 550 + 600,- 550 + 550,- 550 + 600,-1650
+ 600
Sum: 68750
Send Samsung 8 bit command and 8 bit address
Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first
Send with: IrSender.sendSamsung(0xF1, 0x76, <numberOfRepeats>);
rawData[68]:
-1045200
+4500,-4400
+ 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ 650,-1600 + 600,- 500 + 650,- 500 + 650,- 450
+ 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600
+ 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500
+ 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ 600,-1600 + 650,- 500 + 650,- 450 + 650,-1600
+ 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600
+ 650
Sum: 65600
Send Samsung 16 bit command
Send Samsung 16 bit command and address
Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
Send with: IrSender.sendSamsung(0xFFF1, 0x9876, <numberOfRepeats>);
rawData[68]:
-1056350
+4400,-4400
+ 600,-1650 + 550,- 550 + 600,- 550 + 550,- 550
+ 600,-1650 + 550,-1650 + 600,-1650 + 600,-1600
+ 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650
+ 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
+ 600,- 500 + 550,-1700 + 600,-1650 + 550,- 550
+ 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550
+ 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
+ 550,-1650 + 600,- 550 + 600,- 550 + 550,-1650
+ 600
Sum: 68650
rawData[68]:
-1060350
+4500,-4400
+ 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500
+ 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ 600,-1600 + 600,-1650 + 650,-1600 + 650,-1600
+ 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550
+ 600,-1600 + 650,-1600 + 600,-1650 + 650,- 450
+ 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ 600,-1600 + 600,- 550 + 600,- 500 + 650,-1600
+ 650
Sum: 68950
Send Samsung48 16 bit command
Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first
Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, <numberOfRepeats>);
rawData[100]:
-1056750
+4450,-4450
+ 600,-1650 + 600,- 500 + 600,- 550 + 550,- 550
+ 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
+ 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
+ 550,-1650 + 550,-1700 + 550,-1700 + 550,-1650
+ 600,- 550 + 550,-1700 + 550,-1650 + 600,- 550
+ 550,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650
+ 550,- 550 + 600,- 550 + 550,- 550 + 550,-1700
+ 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+ 550,-1650 + 600,- 550 + 550,- 550 + 600,-1650
+ 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550
+ 550,- 550 + 600,-1650 + 550,-1650 + 600,- 550
+ 550
Sum: 95650
rawData[100]:
-1060200
+4550,-4350
+ 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600
+ 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
+ 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600
+ 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600
+ 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450
+ 650
Sum: 95900
Send RC5
Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first
Send with: IrSender.sendRC5(0x11, 0x36, <numberOfRepeats>);
rawData[20]:
rawData[20]:
-1073300
+ 900,- 900
+1750,-1800 +1750,- 900 + 900,- 850 + 900,-1750
@ -505,7 +507,7 @@ Sum: 23100
Send RC5X with 7.th MSB of command set
Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first
Send with: IrSender.sendRC5(0x11, 0x76, <numberOfRepeats>);
rawData[20]:
rawData[20]:
-1031250
+1800,-1750
+ 850,- 900 +1800,- 850 + 900,- 900 + 900,-1750
@ -516,7 +518,7 @@ Sum: 23050
Send RC6
Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first
Send with: IrSender.sendRC6(0xF1, 0x76, <numberOfRepeats>);
rawData[36]:
rawData[36]:
-1028550
+2650,- 900
+ 450,- 900 + 450,- 450 + 450,- 450 + 450,- 850
@ -529,7 +531,7 @@ Sum: 23250
Send JVC
Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first
Send with: IrSender.sendJVC(0xF1, 0x76, <numberOfRepeats>);
rawData[36]:
rawData[36]:
-1037050
+8400,-4150
+ 500,-1600 + 550,- 500 + 500,- 550 + 550,- 500
@ -542,24 +544,24 @@ Sum: 40400
Send Samsung
Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
Send with: IrSender.sendSamsung(0xFFF1, 0x9876, <numberOfRepeats>);
rawData[68]:
-1036350
+4450,-4400
+ 550,-1700 + 600,- 550 + 550,- 550 + 600,- 550
+ 550,-1650 + 600,-1650 + 600,-1650 + 550,-1650
+ 550,-1700 + 600,-1650 + 550,-1650 + 600,-1650
+ 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
+ 550,- 550 + 600,-1650 + 550,-1700 + 550,- 550
+ 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550
+ 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650
+ 550,-1650 + 600,- 550 + 600,- 500 + 600,-1700
+ 550
Sum: 68750
rawData[68]:
-1039800
+4550,-4400
+ 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600
+ 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600
+ 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600
+ 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500
+ 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600
+ 650
Sum: 69000
Send LG
Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first
Send with: IrSender.sendLG(0xF1, 0x9876, <numberOfRepeats>);
rawData[60]:
rawData[60]:
-1054900
+9000,-4150
+ 450,-1600 + 500,-1550 + 500,-1550 + 500,-1600
@ -575,7 +577,7 @@ Sum: 59350
Send MagiQuest
Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first
Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, <numberOfRepeats>);
rawData[112]:
rawData[112]:
-1049950
+ 250,- 850 + 250,- 900 + 250,- 900 + 250,- 900
+ 250,- 900 + 300,- 850 + 250,- 900 + 250,- 900
@ -594,23 +596,45 @@ rawData[112]:
Sum: 63750
Send Bang&Olufsen
- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
- Now print raw data and try to decode it, which must fail!
rawData[112]:
-1053350
+ 250,-2850 + 250,-2850 + 250,-15250 + 250,-2850
+ 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950
+ 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050
+ 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950
+ 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850
+ 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500
+ 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500
+ 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500
+ 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800
+ 350,- 800 + 350,- 800 + 650,- 550 + 300,- 800
+ 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500
+ 350,- 800 + 650,- 500 + 650,- 550 + 300,- 850
+ 300,- 850 + 350,- 800 + 600,- 550 + 600,- 550
+ 300,- 850 + 600,- 550 + 600,- 550 + 650
Sum: 176100
Protocol=UNKNOWN Hash=0x4E0DAC41 22 bits (incl. gap and start) received
- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first
Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, <numberOfRepeats>);
rawData[44]:
-1078450
+ 150,-2850
+ 200,-2900 + 200,-15300 + 200,-2900 + 200,-9100
+ 250,-5950 + 250,-5950 + 250,-5950 + 200,-2900
+ 200,-6000 + 200,-6000 + 200,-9100 + 200,-2900
+ 200,-9100 + 250,-5950 + 250,-5950 + 250,-2850
+ 200,-9100 + 250,-5950 + 250,-2850 + 200,-12200
+ 200
Sum: 136500
rawData[44]:
-15250
+ 250,-2850
+ 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950
+ 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050
+ 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950
+ 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850
+ 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500
+ 650
Sum: 118700
Send Bosewave with no address and 8 command bits
Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
Send with: IrSender.sendBoseWave(0x0, 0x76, <numberOfRepeats>);
rawData[36]:
rawData[36]:
-1044750
+1050,-1450
+ 550,- 450 + 550,-1400 + 550,-1450 + 550,- 450
@ -623,7 +647,7 @@ Sum: 26750
Send FAST
Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
Send with: IrSender.sendFAST(0x0, 0x76, <numberOfRepeats>);
rawData[36]:
rawData[36]:
-1036750
+2100,-1050
+ 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
@ -636,7 +660,7 @@ Sum: 28900
Force buffer overflow by sending 280 marks and spaces
Overflow
Try to increase the "RAW_BUFFER_LENGTH" value of 150 in ../src/UnitTest.cpp
rawData[150]:
rawData[150]:
-1040000
+ 250,- 500
+ 200,- 600 + 200,- 550 + 200,- 500 + 200,- 550
@ -667,7 +691,7 @@ address=0xF2 command=0x87
Send NEC with 8 bit address
Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
Send with: IrSender.sendNEC(0xF2, 0x87, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-3276750
+8850,-4500
+ 550,- 500 + 600,-1650 + 600,- 500 + 600,- 550
@ -681,10 +705,27 @@ rawData[68]:
+ 600
Sum: 67600
Repeat NEC frame for NEC2
Protocol=NEC2 Address=0xF8 Command=0xED Repeat gap=48600us Raw-Data=0x12ED07F8 32 bits LSB first
!Use the NEC2 protocol for sending!
rawData[68]:
-87300
+8950,-4400
+ 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500
+ 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ 600,-1600 + 650,- 500 + 650,-1600 + 600,-1650
+ 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
+ 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ 600
Sum: 67850
Send NEC with 16 bit address
Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
Send with: IrSender.sendNEC(0xF2, 0x87, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-998700
+8900,-4400
+ 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
@ -701,7 +742,7 @@ Sum: 67650
Send NEC2 with 16 bit address
Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
Send with: IrSender.sendNEC(0xF2, 0x87, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1055100
+8950,-4400
+ 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500
@ -718,7 +759,7 @@ Sum: 67800
Send Onkyo (NEC with 16 bit command)
Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first
Send with: IrSender.sendOnkyo(0xF2, 0x8887, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1053400
+8850,-4400
+ 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550
@ -735,7 +776,7 @@ Sum: 62050
Send Apple
Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first
Send with: IrSender.sendApple(0xF2, 0x87, <numberOfRepeats>);
rawData[68]:
rawData[68]:
-1054100
+8900,-4450
+ 550,- 550 + 600,-1650 + 600,-1650 + 600,-1650

View File

@ -5,9 +5,9 @@
"repository":
{
"type": "git",
"url": "https://github.com/z3t0/Arduino-IRremote.git"
"url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git"
},
"version": "4.2.0",
"version": "4.3.1",
"frameworks": "arduino",
"platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
"authors" :

View File

@ -1,9 +1,9 @@
name=IRremote
version=4.2.0
version=4.3.1
author=shirriff, z3t0, ArminJo
maintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>
sentence=Send and receive infrared signals with multiple protocols
paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, FAST, MagiQuest.<br/><br/><b>New: </b>Added untested Uno R4 support. Improved ESP support. Added DECODE_ONKYO. Old decode() prints a message now.<br/><a href="https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md">Release notes</a><br/>
paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, FAST, MagiQuest, Universal Pulse Distance and Pulse Width. NEW: TinyRSender improvements, sendSamsung bug fixes, new fields rawlen and initialGap and new functions stop/startTimer...().
category=Communication
url=https://github.com/Arduino-IRremote/Arduino-IRremote
architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2020-2023 Armin Joachimsmeyer
* Copyright (c) 2020-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -58,8 +58,8 @@ typedef enum {
RC5,
RC6,
SAMSUNG,
SAMSUNGLG,
SAMSUNG48,
SAMSUNG_LG,
SHARP,
SONY,
/* Now the exotic protocols */
@ -71,7 +71,6 @@ typedef enum {
FAST
} decode_type_t;
#define SIRCS_12_PROTOCOL 12
#define SIRCS_15_PROTOCOL 15
#define SIRCS_20_PROTOCOL 20
@ -95,6 +94,7 @@ struct DistanceWidthTimingInfoStruct {
#define IRDATA_FLAGS_TOGGLE_BIT 0x08 ///< Is set if RC5 or RC6 toggle bit is set.
#define IRDATA_TOGGLE_BIT_MASK 0x08 ///< deprecated -is set if RC5 or RC6 toggle bit is set.
#define IRDATA_FLAGS_EXTRA_INFO 0x10 ///< There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID, or in decodedRawDataArray).
#define IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT 0x20 ///< Here we have a repeat of type NEC2 or SamsungLG
#define IRDATA_FLAGS_WAS_OVERFLOW 0x40 ///< irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag.
#define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Value is mainly determined by the (known) protocol.
#define IRDATA_FLAGS_IS_LSB_FIRST 0x00
@ -117,6 +117,11 @@ struct IRData {
#endif
uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above
// These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0.
IRRawlenType rawlen; ///< counter of entries in rawbuf
uint16_t initialGap; ///< rawbuf[0] contains the initial gap of the last frame.
irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR.
};
@ -132,12 +137,9 @@ struct PulseDistanceWidthProtocolConstants {
/*
* Definitions for member PulseDistanceWidthProtocolConstants.Flags
*/
#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20
#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20 // Stop bit is otherwise sent for all pulse distance protocols.
#define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST
#define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST
// 2 definitions for deprecated parameter bool aSendStopBit
#define SEND_STOP_BIT true
#define SEND_NO_STOP_BIT false
/*
* Carrier frequencies for various protocols

View File

@ -39,11 +39,6 @@
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/*
* Check for additional characteristics of timing like length of mark for a constant mark protocol,
* where space length determines the bit value. Requires up to 194 additional bytes of program memory.
*/
//#define DECODE_STRICT_CHECKS
/** \addtogroup Receiving Receiving IR data for multiple protocols
* @{
*/
@ -68,8 +63,8 @@ const char string_Kaseikyo_Mitsubishi[] PROGMEM = "Kaseikyo_Mitsubishi";
const char string_RC5[] PROGMEM = "RC5";
const char string_RC6[] PROGMEM = "RC6";
const char string_Samsung[] PROGMEM = "Samsung";
const char string_Samsung48[] PROGMEM = "Samsung48";
const char string_SamsungLG[] PROGMEM = "SamsungLG";
const char string_Samsung48[] PROGMEM = "Samsung48";
const char string_Sharp[] PROGMEM = "Sharp";
const char string_Sony[] PROGMEM = "Sony";
const char string_BangOlufsen[] PROGMEM = "Bang&Olufsen";
@ -85,7 +80,7 @@ const char string_FAST[] PROGMEM = "FAST";
const char *const ProtocolNames[]
PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, string_LG2,
string_NEC, string_NEC2, string_Onkyo, string_Panasonic, string_Kaseikyo, string_Kaseikyo_Denon, string_Kaseikyo_Sharp,
string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_Samsung48, string_SamsungLG,
string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_SamsungLG, string_Samsung48,
string_Sharp, string_Sony
#if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
, string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST
@ -183,7 +178,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap
#endif
#if !defined(DISABLE_CODE_FOR_RECEIVER)
aSerial->print(' ');
aSerial->print((aIRDataPtr->rawDataPtr->rawlen + 1) / 2, DEC);
aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC);
aSerial->println(F(" bits (incl. gap and start) received"));
#endif
} else {
@ -223,7 +218,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap
#if !defined(DISABLE_CODE_FOR_RECEIVER)
if (aPrintRepeatGap) {
aSerial->print(F(" gap="));
aSerial->print((uint32_t) aIRDataPtr->rawDataPtr->rawbuf[0] * MICROS_PER_TICK);
aSerial->print((uint32_t) aIRDataPtr->initialGap * MICROS_PER_TICK);
aSerial->print(F("us"));
}
#else

View File

@ -51,7 +51,7 @@
//#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
//
/*
* Check for additional characteristics of timing like length of mark for a constant mark protocol,
* Check for additional required characteristics of timing like length of mark for a constant mark protocol,
* where space length determines the bit value. Requires up to 194 additional bytes of program memory.
*/
//#define DECODE_STRICT_CHECKS
@ -198,7 +198,7 @@ void IRReceiveTimerInterruptHandler() {
// Flag up a read OverflowFlag; Stop the state machine
irparams.OverflowFlag = true;
irparams.StateForISR = IR_REC_STATE_STOP;
#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
/*
* Call callback if registered (not NULL)
*/
@ -224,7 +224,7 @@ void IRReceiveTimerInterruptHandler() {
* Don't reset TickCounterForISR; keep counting width of next leading space
*/
irparams.StateForISR = IR_REC_STATE_STOP;
#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
/*
* Call callback if registered (not NULL)
*/
@ -287,7 +287,7 @@ void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8
setReceivePin(aReceivePin);
#if !defined(NO_LED_FEEDBACK_CODE)
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
if (aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE;
}
@ -309,19 +309,40 @@ void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8
void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) {
irparams.IRReceivePin = aReceivePinNumber;
#if defined(__AVR__)
irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber);
irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber));
# if defined(__digitalPinToBit)
if (__builtin_constant_p(aReceivePinNumber)) {
irparams.IRReceivePinMask = 1UL << (__digitalPinToBit(aReceivePinNumber));
} else {
irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
}
# else
irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
# endif
# if defined(__digitalPinToPINReg)
/*
* This code is 54 bytes smaller, if aReceivePinNumber is a constant :-), but 38 byte longer if it is not constant (,which is not likely).
*/
if (__builtin_constant_p(aReceivePinNumber)) {
irparams.IRReceivePinPortInputRegister = __digitalPinToPINReg(aReceivePinNumber);
} else {
irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
}
# else
irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
# endif
#endif
// Set pin mode once. pinModeFast makes no difference here :-(
pinMode(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32
// Set pin mode once. pinModeFast makes no difference if used, but saves 224 if not referenced :-(
pinModeFast(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32
}
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
/**
* Sets the function to call if a protocol message has arrived
*/
void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) {
irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction;
}
#endif
/**
* Start the receiving process.
@ -342,6 +363,19 @@ void IRrecv::start() {
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
}
/*
* Do not resume() reading of IR data
*/
void IRrecv::restartTimer() {
// Setup for cyclic 50 us interrupt
timerConfigForReceive(); // no interrupts enabled here!
// Timer interrupt is enabled after state machine reset
timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
#ifdef _IR_MEASURE_TIMING
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
}
/**
* Alias for start().
*/
@ -358,10 +392,18 @@ void IRrecv::start(uint32_t aMicrosecondsToAddToGapCounter) {
irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
start();
}
void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) {
irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
restartTimer();
}
void IRrecv::startWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
irparams.TickCounterForISR += aTicksToAddToGapCounter;
start();
}
void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
irparams.TickCounterForISR += aTicksToAddToGapCounter;
restartTimer();
}
void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) {
irparams.TickCounterForISR += aTicksToAddToInternalTickCounter;
@ -385,6 +427,10 @@ void IRrecv::restartAfterSend() {
void IRrecv::stop() {
timerDisableReceiveInterrupt();
}
void IRrecv::stopTimer() {
timerDisableReceiveInterrupt();
}
/**
* Alias for stop().
*/
@ -407,10 +453,11 @@ bool IRrecv::isIdle() {
}
/**
* Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame
* Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame.
* Internal counting of gap timing is independent of StateForISR and therefore independent of call time of resume().
*/
void IRrecv::resume() {
// check allows to call resume at arbitrary places or more than once
// This check allows to call resume at arbitrary places or more than once
if (irparams.StateForISR == IR_REC_STATE_STOP) {
irparams.StateForISR = IR_REC_STATE_IDLE;
}
@ -433,11 +480,16 @@ void IRrecv::initDecodedIRData() {
} else {
decodedIRData.flags = IRDATA_FLAGS_EMPTY;
// save last protocol, command and address for repeat handling (where they are compared or copied back :-))
lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC and LG), so we must keep the original one
lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC, Samsung and LG), so we must keep the original one
lastDecodedCommand = decodedIRData.command;
lastDecodedAddress = decodedIRData.address;
}
//These 2 variables allow to call resume() directly after decode, if no dump is required. since 4.3.0.
decodedIRData.initialGap = decodedIRData.rawDataPtr->rawbuf[0];
decodedIRData.rawlen = decodedIRData.rawDataPtr->rawlen;
decodedIRData.protocol = UNKNOWN;
decodedIRData.command = 0;
decodedIRData.address = 0;
@ -650,7 +702,7 @@ bool IRrecv::decode() {
* @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first.
* @return true If decoding was successful
*/
bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros,
bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
@ -722,7 +774,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8
} else {
tDecodedData |= tMask;
}
IR_TRACE_PRINTLN('1');
IR_TRACE_PRINTLN(F("=> 1"));
} else {
#if defined DECODE_STRICT_CHECKS
/*
@ -761,7 +813,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8
}
#endif
// do not set the bit
IR_TRACE_PRINTLN('0');
IR_TRACE_PRINTLN(F("=> 0"));
}
#if defined DECODE_STRICT_CHECKS
// If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
@ -793,7 +845,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8
* @return true if decoding was successful
*/
bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
uint_fast8_t aStartOffset) {
IRRawlenType aStartOffset) {
return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
@ -803,9 +855,9 @@ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a
/*
* Static variables for the getBiphaselevel function
*/
uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array
uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals.
uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array
uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals.
uint16_t sBiphaseTimeUnit;
void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) {
@ -833,7 +885,7 @@ void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBip
uint_fast8_t IRrecv::getBiphaselevel() {
uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK)
if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawDataPtr->rawlen) {
if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawlen) {
return SPACE; // After end of recorded buffer, assume space.
}
@ -872,10 +924,12 @@ uint_fast8_t IRrecv::getBiphaselevel() {
return tLevelOfCurrentInterval;
}
#if defined(DECODE_HASH)
/**********************************************************************************************************************
* Internal Hash decode function
**********************************************************************************************************************/
#define FNV_PRIME_32 16777619 ///< used for decodeHash()
#define FNV_BASIS_32 2166136261 ///< used for decodeHash()
/**
* Compare two (tick) values for Hash decoder
* Use a tolerance of 20% to enable e.g. 500 and 600 (NEC timing) to be equal
@ -891,19 +945,15 @@ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
return 1;
}
#define FNV_PRIME_32 16777619 ///< used for decodeHash()
#define FNV_BASIS_32 2166136261 ///< used for decodeHash()
/**
* decodeHash - decode an arbitrary IR code.
* Instead of decoding using a standard encoding scheme
* (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value.
*
* The algorithm: look at the sequence of MARK signals, and see if each one
* is shorter (0), the same length (1), or longer (2) than the previous.
* Do the same with the SPACE signals. Hash the resulting sequence of 0's,
* 1's, and 2's to a 32-bit value. This will give a unique value for each
* different code (probably), for most code systems.
* The algorithm: look at the sequence of MARK and SPACE signals, and see if each one
* is shorter (0), the same length (1), or longer (2) than the previous MARK or SPACE.
* Hash the resulting sequence of 0's, 1's, and 2's to a 32-bit value.
* This will give a unique value for each different code (probably), for most code systems.
*
* Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
* Converts the raw code values into a 32-bit hash code.
@ -916,15 +966,11 @@ bool IRrecv::decodeHash() {
unsigned long hash = FNV_BASIS_32; // the result is the same no matter if we use a long or unsigned long variable
// Require at least 6 samples to prevent triggering on noise
if (decodedIRData.rawDataPtr->rawlen < 6) {
if (decodedIRData.rawlen < 6) {
return false;
}
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
#endif
for (i = 1; (i + 2) < decodedIRData.rawDataPtr->rawlen; i++) {
for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) {
// Compare mark with mark and space with space
uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]);
// Add value into the hash
hash = (hash * FNV_PRIME_32) ^ value;
@ -958,7 +1004,6 @@ bool IRrecv::decodeHashOld(decode_results *aResults) {
return true;
}
#endif // DECODE_HASH
/**********************************************************************************************************************
* Match functions
@ -1113,10 +1158,10 @@ bool IRrecv::checkForRecordGapsMicros(Print *aSerial) {
* is smaller than known value for protocols (Sony with around 24 ms)
*/
if (decodedIRData.protocol <= PULSE_DISTANCE
&& decodedIRData.rawDataPtr->rawbuf[0] < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) {
&& decodedIRData.initialGap < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) {
aSerial->println();
aSerial->print(F("Space of "));
aSerial->print(decodedIRData.rawDataPtr->rawbuf[0] * MICROS_PER_TICK);
aSerial->print(decodedIRData.initialGap * MICROS_PER_TICK);
aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of "));
aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD);
aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc.."));
@ -1182,7 +1227,7 @@ void printActiveIRProtocols(Print *aSerial) {
aSerial->print(F("Lego Power Functions, "));
#endif
#if defined(DECODE_BOSEWAVE)
aSerial->print(F("Bosewave , "));
aSerial->print(F("Bosewave, "));
#endif
#if defined(DECODE_MAGIQUEST)
aSerial->print(F("MagiQuest, "));
@ -1233,7 +1278,8 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf
uint32_t IRrecv::getTotalDurationOfRawData() {
uint16_t tSumOfDurationTicks = 0;
for (uint_fast8_t i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i];
}
return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK;
@ -1242,22 +1288,32 @@ uint32_t IRrecv::getTotalDurationOfRawData() {
/**
* Function to print values and flags of IrReceiver.decodedIRData in one line.
* Ends with println().
* !!!Attention: The result differs on a 8 bit or 32 bit platform!!!
*
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
*/
void IRrecv::printIRSendUsage(Print *aSerial) {
if (decodedIRData.protocol != UNKNOWN
&& (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) {
if (decodedIRData.flags & IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT) {
/*
* Here we have a repeat of type NEC2 or SamsungLG. -> Inform the user to use this and not the initial protocol for sending.
*/
Serial.print(F("!Use the "));
Serial.print(getProtocolString());
Serial.println(F(" protocol for sending!"));
} else {
if (decodedIRData.protocol != UNKNOWN
&& (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) {
#if defined(DECODE_DISTANCE_WIDTH)
aSerial->print(F("Send with:"));
uint_fast8_t tNumberOfArrayData = 0;
if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) {
# if __INT_WIDTH__ < 32
aSerial->print(F("Send on a 8 bit platform with: "));
tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1;
if(tNumberOfArrayData > 1) {
aSerial->println();
aSerial->print(F(" uint32_t tRawData[]={0x"));
# else
aSerial->print(F("Send on a 32 bit platform with: "));
tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1;
if(tNumberOfArrayData > 1) {
aSerial->println();
@ -1274,19 +1330,22 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
}
}
aSerial->println(F("};"));
aSerial->print(F(" "));
aSerial->print(F(" "));
}
} else {
aSerial->print(F("Send with: "));
}
aSerial->print(F(" IrSender.send"));
aSerial->print(F("IrSender.send"));
#else
aSerial->print(F("Send with: IrSender.send"));
aSerial->print(F("Send with: IrSender.send"));
#endif
#if defined(DECODE_DISTANCE_WIDTH)
if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) {
#endif
aSerial->print(getProtocolString());
aSerial->print(F("(0x"));
aSerial->print(getProtocolString());
aSerial->print(F("(0x"));
#if defined(DECODE_MAGIQUEST)
if (decodedIRData.protocol == MAGIQUEST) {
# if (__INT_WIDTH__ < 32)
@ -1298,20 +1357,20 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
aSerial->print(decodedIRData.address, HEX);
}
#else
/*
* New decoders have address and command
*/
aSerial->print(decodedIRData.address, HEX);
/*
* New decoders have address and command
*/
aSerial->print(decodedIRData.address, HEX);
#endif
aSerial->print(F(", 0x"));
aSerial->print(decodedIRData.command, HEX);
if (decodedIRData.protocol == SONY) {
aSerial->print(F(", 2, "));
aSerial->print(decodedIRData.numberOfBits);
} else {
aSerial->print(F(", <numberOfRepeats>"));
}
aSerial->print(F(", 0x"));
aSerial->print(decodedIRData.command, HEX);
if (decodedIRData.protocol == SONY) {
aSerial->print(F(", 2, "));
aSerial->print(decodedIRData.numberOfBits);
} else {
aSerial->print(F(", <numberOfRepeats>"));
}
#if defined(DECODE_DISTANCE_WIDTH)
} else {
@ -1354,8 +1413,9 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
aSerial->print(decodedIRData.extra, HEX);
}
#endif
aSerial->print(F(");"));
aSerial->println();
aSerial->print(F(");"));
aSerial->println();
}
}
}
@ -1378,7 +1438,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
# endif
#endif
aSerial->print(' ');
aSerial->print((decodedIRData.rawDataPtr->rawlen + 1) / 2, DEC);
aSerial->print((decodedIRData.rawlen + 1) / 2, DEC);
aSerial->println(F(" bits received"));
} else {
/*
@ -1411,10 +1471,9 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
*/
void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
uint8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Get it once here in order to print quite consistent data, even if ISR is running
// Print Raw data
aSerial->print(F("rawData["));
aSerial->print(tRawlen, DEC);
aSerial->print(decodedIRData.rawlen, DEC);
aSerial->println(F("]: "));
/*
@ -1422,15 +1481,10 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
*/
aSerial->print(F(" -"));
if (aOutputMicrosecondsInsteadOfTicks) {
aSerial->println((uint32_t) decodedIRData.rawDataPtr->rawbuf[0] * MICROS_PER_TICK, DEC);
aSerial->println((uint32_t) decodedIRData.initialGap * MICROS_PER_TICK, DEC);
} else {
aSerial->println(decodedIRData.rawDataPtr->rawbuf[0], DEC);
aSerial->println(decodedIRData.initialGap, DEC);
}
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
#endif
// Newline is printed every 8. value, if tCounterForNewline % 8 == 0
uint_fast8_t tCounterForNewline = 6; // first newline is after the 2 values of the start bit
@ -1451,7 +1505,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
uint32_t tDuration;
uint16_t tSumOfDurationTicks = 0;
for (i = 1; i < tRawlen; i++) {
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (aOutputMicrosecondsInsteadOfTicks) {
tDuration = tCurrentTicks * MICROS_PER_TICK;
@ -1478,7 +1532,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
}
aSerial->print(tDuration, DEC);
if ((i & 1) && (i + 1) < tRawlen) {
if ((i & 1) && (i + 1) < decodedIRData.rawlen) {
aSerial->print(','); //',' not required for last one
}
@ -1516,16 +1570,11 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr
aSerial->print(F("uint8_t rawTicks[")); // variable type, array name
}
aSerial->print(decodedIRData.rawDataPtr->rawlen - 1, DEC); // array size
aSerial->print(decodedIRData.rawlen - 1, DEC); // array size
aSerial->print(F("] = {")); // Start declaration
// Dump data
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
#endif
for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
if (i & 1) {
@ -1545,10 +1594,8 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr
tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks;
aSerial->print(tTicks);
}
if (i + 1 < decodedIRData.rawDataPtr->rawlen)
aSerial->print(','); // ',' not required on last one
if (!(i & 1))
aSerial->print(' ');
if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one
if (!(i & 1)) aSerial->print(' ');
}
// End declaration
@ -1574,12 +1621,8 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr
void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) {
// Store data, skip leading space#
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t i;
#else
unsigned int i;
#endif
for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) {
IRRawlenType i;
for (i = 1; i < decodedIRData.rawlen; i++) {
uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
if (i & 1) {
// Mark

View File

@ -95,7 +95,7 @@ void IRsend::begin(){
*/
void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
#if !defined(NO_LED_FEEDBACK_CODE)
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
if(aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
}
@ -143,7 +143,7 @@ void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t
#endif
#if !defined(NO_LED_FEEDBACK_CODE)
bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
if (aEnableLEDFeedback) {
tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
}
@ -220,7 +220,7 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) {
} else if (tProtocol == SAMSUNG48) {
sendSamsung48(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == SAMSUNG_LG) {
} else if (tProtocol == SAMSUNGLG) {
sendSamsungLG(tAddress, tCommand, aNumberOfRepeats);
} else if (tProtocol == SONY) {
@ -341,7 +341,7 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma
} else if (aProtocol == SAMSUNG48) {
sendSamsung48(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SAMSUNG_LG) {
} else if (aProtocol == SAMSUNGLG) {
sendSamsungLG(aAddress, aCommand, aNumberOfRepeats);
} else if (aProtocol == SONY) {
@ -466,15 +466,24 @@ void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t a
if (i & 1) {
// Odd
space(duration);
# if defined(LOCAL_DEBUG)
Serial.print(F("S="));
# endif
} else {
mark(duration);
# if defined(LOCAL_DEBUG)
Serial.print(F("M="));
# endif
}
# if defined(LOCAL_DEBUG)
Serial.println(duration);
# endif
}
#endif
}
/**
* New function using an 8 byte tick timing array in FLASH to save program memory
* New function using an 8 byte tick (50 us) timing array in FLASH to save program memory
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
@ -484,16 +493,26 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
uint_fast16_t duration;
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
uint_fast16_t duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK;
duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK;
if (i & 1) {
// Odd
space(duration);
# if defined(LOCAL_DEBUG)
Serial.print(F("S="));
# endif
} else {
mark(duration);
# if defined(LOCAL_DEBUG)
Serial.print(F("M="));
# endif
}
}
IRLedOff(); // Always end with the LED off
# if defined(LOCAL_DEBUG)
Serial.println(duration);
# endif
#endif
}
@ -502,21 +521,8 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
* For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on.
* The output always ends with a space
* Stop bit is always sent
* @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols.
*/
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit,
uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidthFromArray(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros,
aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats);
}
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats) {
@ -526,7 +532,6 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, Distanc
aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
aNumberOfRepeats);
}
void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
@ -597,6 +602,9 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_
* For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on.
* The output always ends with a space
* Stop bit is always sent
* @param aNumberOfBits Number of bits from aDecodedRawDataArray to be actually sent.
* @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified
* then it is called without leading and trailing space.
*/
void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
@ -673,7 +681,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants
}
/**
* Sends PulseDistance frames and repeats and enables receiver again
* Sends PulseDistance frames and repeats
* @param aProtocolConstants The constants to use for sending this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
@ -693,10 +701,14 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
if (aNumberOfRepeats < 0) {
if (aProtocolConstants->SpecialSendRepeatFunction != NULL) {
/*
* Send only a special repeat and return
*/
aProtocolConstants->SpecialSendRepeatFunction();
return;
} else {
aNumberOfRepeats = 0; // send a plain frame as repeat
// Send only one plain frame (as repeat)
aNumberOfRepeats = 0;
}
}
@ -708,7 +720,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
unsigned long tStartOfFrameMillis = millis();
if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aProtocolConstants->SpecialSendRepeatFunction != NULL) {
// send special repeat
// send special repeat, if specified and we are not in the first loop
aProtocolConstants->SpecialSendRepeatFunction();
} else {
/*
@ -722,12 +734,12 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
tNumberOfCommands--;
// skip last delay!
if (tNumberOfCommands > 0) {
auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis;
/*
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
if (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) {
delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis);
if (aProtocolConstants->RepeatPeriodMillis > tCurrentFrameDurationMillis) {
delay(aProtocolConstants->RepeatPeriodMillis - tCurrentFrameDurationMillis);
}
}
}
@ -738,23 +750,11 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
* @param aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aFlags, aRepeatPeriodMillis Values to use for sending this protocol, also contained in the PulseDistanceWidthProtocolConstants of this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
* @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols.
* @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified
* then it is called without leading and trailing space.
* @param aSpecialSendRepeatFunction If NULL, the first frame is repeated completely, otherwise this function is used for sending the repeat frame.
*/
void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData,
uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
void (*aSpecialSendRepeatFunction)()) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidth(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros,
aZeroSpaceMicros, aData, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats, aSpecialSendRepeatFunction);
}
void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData,
uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
@ -802,9 +802,12 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader
}
/**
* Sends PulseDistance data
* Sends PulseDistance from data contained in parameter using ProtocolConstants structure for timing etc.
* The output always ends with a space
* Each additional call costs 16 bytes program memory
* @param aProtocolConstants The constants to use for sending this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
*/
void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits) {
@ -815,18 +818,13 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr
}
/**
* Sends PulseDistance data
* Sends PulseDistance data with timing parameters and flag parameters.
* The output always ends with a space
* @param aOneMarkMicros Timing for sending this protocol.
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
* @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols.
*/
void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit) {
uint8_t tFlags = 0;
if (aMSBFirst) {
tFlags = PROTOCOL_IS_MSB_FIRST;
}
(void) aSendStopBit;
sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits, tFlags);
}
void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
@ -862,6 +860,7 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp
/*
* Stop bit is sent for all pulse distance protocols i.e. aOneMarkMicros == aZeroMarkMicros.
* Therefore it is not sent for Sony and Magiquest :-)
* For sending from an array, no intermediate stop bit must be sent for first data chunk.
*/
if (!(aFlags & SUPPRESS_STOP_BIT_FOR_THIS_DATA) && aOneMarkMicros == aZeroMarkMicros) {
// Send stop bit here
@ -882,6 +881,8 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp
* 1 -> space+mark
* The output always ends with a space
* can only send 31 bit data, since we put the start bit as 32th bit on front
* @param aData uint32 or uint64 holding the bits to be sent.
* @param aNumberOfBits Number of bits from aData to be actually sent.
*/
void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
@ -935,6 +936,13 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas
* This function may affect the state of feedback LED.
* Period time is 26 us for 38.46 kHz, 27 us for 37.04 kHz, 25 us for 40 kHz.
* On time is 8 us for 30% duty cycle
*
* The mark() function relies on the correct implementation of:
* delayMicroseconds() for pulse time, and micros() for pause time.
* The delayMicroseconds() of pulse time is guarded on AVR CPU's with noInterrupts() / interrupts().
* At the start of pause time, interrupts are enabled once, the rest of the pause is also guarded on AVR CPU's with noInterrupts() / interrupts().
* The maximum length of an interrupt during sending should not exceed 26 us - 8 us = 18 us, otherwise timing is disturbed.
* This disturbance is no problem, if the exceedance is small and does not happen too often.
*/
void IRsend::mark(uint16_t aMarkMicros) {
@ -960,7 +968,10 @@ void IRsend::mark(uint16_t aMarkMicros) {
* Here we generate no carrier PWM, just simulate an active low receiver signal.
*/
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
// Here we have no hardware supported Open Drain outputs, so we must mimicking it
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
digitalWriteFast(sendPin, HIGH); // Set output to active high.
# else
digitalWriteFast(sendPin, LOW); // Set output to active low.
# endif
@ -1002,7 +1013,7 @@ void IRsend::mark(uint16_t aMarkMicros) {
// 4.3 us from do{ to pin setting if sendPin is no constant
digitalWriteFast(sendPin, HIGH);
# endif
delayMicroseconds(periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait.
delayMicroseconds (periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait.
/*
* Output the PWM pause
@ -1106,6 +1117,8 @@ void IRsend::IRLedOff() {
# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
digitalWriteFast(sendPin, LOW); // prepare for all next active states.
pinModeFast(sendPin, INPUT);// inactive state for open drain
# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN)
digitalWriteFast(sendPin, LOW); // Set output to inactive low.
# else
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
# endif

View File

@ -36,10 +36,10 @@
#ifndef _IR_VERSION_HPP
#define _IR_VERSION_HPP
#define VERSION_IRREMOTE "4.2.0"
#define VERSION_IRREMOTE "4.3.1"
#define VERSION_IRREMOTE_MAJOR 4
#define VERSION_IRREMOTE_MINOR 2
#define VERSION_IRREMOTE_PATCH 0
#define VERSION_IRREMOTE_MINOR 3
#define VERSION_IRREMOTE_PATCH 1
/*
* Macro to convert 3 version parts into an integer

View File

@ -9,6 +9,15 @@
#include "IRremote.hpp"
#warning Thank you for using the IRremote library!
#warning It seems, that you are using a old version 2.0 code / example.
#warning This version is no longer supported!
#warning Please use one of the new code examples from the library available at "File > Examples > Examples from Custom Libraries / IRremote".
#warning Or downgrade your library to version 2.6.0.
#warning Start with the SimpleReceiver or SimpleSender example.
#warning The examples are documented here: https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library
#warning A guide how to convert your 2.0 program is here: https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version
/**********************************************************************************************************************
* The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials
* This function calls the old MSB first decoders and fills only the 3 variables:
@ -26,6 +35,7 @@ bool IRrecv::decode(decode_results *aResults) {
Serial.println(F("This version is no longer supported!"));
Serial.println(F("Please use one of the new code examples from the library,"));
Serial.println(F(" available at \"File > Examples > Examples from Custom Libraries / IRremote\"."));
Serial.println(F("Or downgrade your library to version 2.6.0."));
Serial.println();
Serial.println(F("Start with the SimpleReceiver or SimpleSender example."));
Serial.println();

View File

@ -158,7 +158,7 @@
*/
#if !defined(RECORD_GAP_MICROS)
// To change this value, you simply can add a line #define "RECORD_GAP_MICROS <My_new_value>" in your ino file before the line "#include <IRremote.hpp>"
#define RECORD_GAP_MICROS 5000 // FREDRICH28AC / LG2 header space is 9700, NEC header space is 4500
#define RECORD_GAP_MICROS 8000 // RECS80 (https://www.mikrocontroller.net/articles/IRMP#RECS80) 1 bit space is 7500µs , NEC header space is 4500
#endif
/**
* Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value.
@ -192,7 +192,7 @@
#if (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED)
# if !defined(SEND_PWM_BY_TIMER)
#define SEND_PWM_BY_TIMER // the best and default method for ESP32 etc.
#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default. If this is not intended, deactivate the line in IRremote.hpp over this warning message in file IRremote.hpp.
#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default, since we have the resources and timing is more exact than the software generated one. If this is not intended, deactivate the line in IRremote.hpp over this warning message in file IRremote.hpp.
# endif
#else
# if defined(SEND_PWM_BY_TIMER)
@ -271,6 +271,8 @@
#warning INFO: No definition for LED_BUILTIN found -> default LED feedback is disabled.
# endif
#include "IRFeedbackLED.hpp"
# else
void disableLEDFeedback() {}; // dummy function for examples
# endif
#include "LongUnion.h" // used in most decoders

View File

@ -79,6 +79,11 @@
#error RAW_BUFFER_LENGTH must be even, since the array consists of space / mark pairs.
#endif
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
typedef uint_fast8_t IRRawlenType;
#else
typedef unsigned int IRRawlenType;
#endif
/****************************************************
* Declarations for the receiver Interrupt Service Routine
****************************************************/
@ -100,16 +105,12 @@ struct irparams_struct {
volatile uint8_t *IRReceivePinPortInputRegister;
uint8_t IRReceivePinMask;
#endif
volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition.
#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is independent of state or resume().
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP
#endif
bool OverflowFlag; ///< Raw buffer OverflowFlag occurred
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
uint_fast8_t rawlen; ///< counter of entries in rawbuf
#else
uint_fast16_t rawlen; ///< counter of entries in rawbuf
#endif
IRRawlenType rawlen; ///< counter of entries in rawbuf
uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
};
@ -124,6 +125,8 @@ typedef uint64_t IRRawDataType;
/*
* Debug directives
* Outputs with IR_DEBUG_PRINT can only be activated by defining DEBUG!
* If LOCAL_DEBUG is defined in one file, all outputs with IR_DEBUG_PRINT are still suppressed.
*/
#if defined(DEBUG) || defined(TRACE)
# define IR_DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
@ -162,7 +165,7 @@ struct decode_results {
uint16_t magnitude; // deprecated, moved to decodedIRData.extra ///< Used by MagiQuest [16-bits]
bool isRepeat; // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected
// next 3 values are copies of irparams values - see IRremoteint.h
// next 3 values are copies of irparams_struct values - see above
uint16_t *rawbuf; // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks
uint_fast8_t rawlen; // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf
bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long
@ -178,16 +181,22 @@ public:
IRrecv(uint_fast8_t aReceivePin);
IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin);
void setReceivePin(uint_fast8_t aReceivePinNumber);
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
void registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void));
#endif
/*
* Stream like API
*/
void begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin =
USE_DEFAULT_FEEDBACK_LED_PIN);
void restartTimer();
void start();
void enableIRIn(); // alias for start
void start(uint32_t aMicrosecondsToAddToGapCounter);
void restartTimer(uint32_t aMicrosecondsToAddToGapCounter);
void startWithTicksToAdd(uint16_t aTicksToAddToGapCounter);
void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter);
void restartAfterSend();
void addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter);
@ -197,6 +206,7 @@ public:
IRData* read(); // returns decoded data
// write is a method of class IRsend below
// size_t write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats = NO_REPEATS);
void stopTimer();
void stop();
void disableIRIn(); // alias for stop
void end(); // alias for stop
@ -243,12 +253,12 @@ public:
* The main decoding functions used by the individual decoders
*/
bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
uint_fast8_t aStartOffset = 3);
IRRawlenType aStartOffset = 3);
bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros,
bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst);
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint_fast8_t aStartClockCount,
uint_fast8_t aValueOfSpaceToMarkTransition, uint16_t aBiphaseTimeUnit);
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit);
@ -312,7 +322,7 @@ public:
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks);
bool checkForRecordGapsMicros(Print *aSerial);
IRData decodedIRData; // New: decoded IR data for the application
IRData decodedIRData; // Decoded IR data for the application
// Last decoded IR data for repeat detection and parity for Denon autorepeat
decode_type_t lastDecodedProtocol;
@ -415,15 +425,22 @@ public:
IRsend();
/*
* IR_SEND_PIN is defined
* IR_SEND_PIN is defined or fixed by timer, value of IR_SEND_PIN is then "DeterminedByTimer"
*/
#if defined(IR_SEND_PIN)
void begin();
void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
// The default parameter allowed to specify IrSender.begin(7); without errors, if IR_SEND_PIN was defined. But the semantics is not the one the user expect.
void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin); // 4.3.1 Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter
// The next function is a dummy to avoid acceptance of pre 4.3 calls to begin(DISABLE_LED_FEEDBACK);
void begin(uint8_t aSendPin)
# if !defined (DOXYGEN)
__attribute__ ((deprecated ("Error: IR_SEND_PIN is still defined, therefore the function begin(aSendPin) is NOT available. You must disable '#define IR_SEND_PIN' to enable this function.")));
# endif
// The next function is a dummy to avoid acceptance of pre 4.0 calls to begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK);
void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback)
# if !defined (DOXYGEN)
__attribute__ ((deprecated ("You must use begin(ENABLE_LED_FEEDBACK) or begin(DISABLE_LED_FEEDBACK) since version 4.0.")));
__attribute__ ((deprecated ("You must use begin() and enableLEDFeedback() or disableLEDFeedback() since version 4.3.")));
# endif
#else
IRsend(uint_fast8_t aSendPin);
@ -445,11 +462,6 @@ public:
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit,
uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
__attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required.")));
void sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
@ -471,9 +483,6 @@ public:
__attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required.")));
void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags);
void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit)
__attribute__ ((deprecated ("Since version 4.1.0 last parameter aSendStopBit is not longer required.")));
void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
void mark(uint16_t aMarkMicros);
@ -533,6 +542,8 @@ public:
void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
void sendSamsungLGRepeat();
void sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats);
void sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats);
void sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats);
void sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNumberOfRepeats);
void sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats);
void sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); // redirected to sendDenon
@ -591,6 +602,8 @@ public:
void sendSharp(uint16_t address, uint16_t command);
void sendSAMSUNG(unsigned long data, int nbits);
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung().")));
void sendSamsungMSB(unsigned long data, int nbits);
void sendSonyMSB(unsigned long data, int nbits);
void sendSony(unsigned long data,
int nbits)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).")));

View File

@ -94,6 +94,7 @@ union LongUnion {
int16_t Words[2];
uint32_t ULong;
int32_t Long;
float Float;
};
#endif // _LONG_UNION_H
@ -140,6 +141,12 @@ union LongLongUnion {
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

View File

@ -34,9 +34,9 @@
* @{
*/
#define VERSION_TINYIR "1.2.0"
#define VERSION_TINYIR_MAJOR 1
#define VERSION_TINYIR_MINOR 2
#define VERSION_TINYIR "2.1.0"
#define VERSION_TINYIR_MAJOR 2
#define VERSION_TINYIR_MINOR 1
#define VERSION_TINYIR_PATCH 0
// The change log is at the bottom of the file
@ -77,15 +77,15 @@
* - 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
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
*/
Sum: 28900
*/
#define FAST_KHZ 38
#define FAST_ADDRESS_BITS 0 // No address
#define FAST_COMMAND_BITS 16 // Command and inverted command (parity)
@ -134,6 +134,8 @@ Sum: 28900
#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
@ -158,36 +160,12 @@ Sum: 28900
#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.
* 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
* 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.
*/
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
// 8 bit address here
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
extern void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags); // Standard NEC callback
# else
extern void handleReceivedTinyIRData(uint8_t aAddress, uint16_t aCommand, uint8_t aFlags); // If SUPPORT_ONKYO_16_BIT_COMMAND is defined
# endif
# else // TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
// 16 bit address here
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
extern void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, uint8_t aFlags);
# else
extern void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags);
# endif
# endif
#else
// FAST protocol - No address here
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
extern void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags); // Standard FAST callback
# else
extern void handleReceivedTinyIRData(uint16_t aCommand, uint8_t aFlags); // If "TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false" is defined. 16 bit without parity.
# endif
extern void handleReceivedTinyIRData();
#endif
#if !defined(MICROS_IN_ONE_SECOND)
@ -248,8 +226,7 @@ struct TinyIRReceiverStruct {
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
/**
* Can be used by the callback to transfer received data to main loop for further processing.
* E.g. with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData;
* 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)
@ -268,25 +245,32 @@ struct TinyIRReceiverCallbackDataStruct {
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, to avoid multiple evaluations of the same IR frame.
};
extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
bool isIRReceiverAttachedForTinyReceiver();
bool initPCIInterruptForTinyReceiver();
bool enablePCIInterruptForTinyReceiver();
void disablePCIInterruptForTinyReceiver();
bool isTinyReceiverIdle();
#if defined(USE_FAST_PROTOCOL)
void printTinyReceiverResultMinimal(Print *aSerial, uint16_t aCommand, uint8_t aFlags);
#else
void printTinyReceiverResultMinimal(Print *aSerial, uint8_t aAddress, uint8_t aCommand, uint8_t aFlags);
#endif
void printTinyReceiverResultMinimal(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); // Send NEC with 16 bit command, even if aCommand < 0x100
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);
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);
/*
* 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.

View File

@ -28,7 +28,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2023 Armin Joachimsmeyer
* Copyright (c) 2022-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -58,9 +58,11 @@
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory.
* - 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 fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
*/
#ifndef _TINY_IR_RECEIVER_HPP
@ -74,7 +76,11 @@
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
/*
* Protocol selection
*/
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
@ -100,6 +106,7 @@
//#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;
/*
* Set input pin and output pin definitions etc.
@ -143,7 +150,7 @@ TinyIRReceiverStruct TinyIRReceiverControl;
* 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 handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition);
extern void handleTinyReceivedIRData();
#if defined(LOCAL_DEBUG)
uint32_t sMicrosOfGap; // The length of the gap before the start bit
@ -319,7 +326,7 @@ void IRPinChangeInterruptHandler(void) {
*/
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
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
@ -332,15 +339,15 @@ void IRPinChangeInterruptHandler(void) {
#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;
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
#else
TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED;
#endif
# if defined(LOCAL_DEBUG)
Serial.print(F("Parity check for command failed. Command="));
Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX);
Serial.print(F(" parity="));
Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX);
Serial.print(F("Parity check for command failed. Command="));
Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX);
Serial.print(F(" parity="));
Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX);
# endif
#else
// No address, so command and parity are in the lowest bytes
@ -363,34 +370,37 @@ void IRPinChangeInterruptHandler(void) {
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
interrupts(); // enable interrupts, so delay() etc. works in callback
#endif
handleReceivedTinyIRData(
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
TinyIRReceiverControl.IRRawData.UBytes[0],
// Here we have 8 bit address
TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UBytes[0];
# else
// Here we have 16 bit address
TinyIRReceiverControl.IRRawData.UWord.LowWord,
// 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
TinyIRReceiverControl.IRRawData.UBytes[2],
// Here we have 8 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[2];
# else
// Here we have 16 bit command
TinyIRReceiverControl.IRRawData.UWord.HighWord,
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord.HighWord;
# endif
#else
// Here we have NO address
#else
// Here we have NO address
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
// Here we have 8 bit command
TinyIRReceiverControl.IRRawData.UBytes[0],
// Here we have 8 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[0];
# else
// Here we have 16 bit command
TinyIRReceiverControl.IRRawData.UWord,
// Here we have 16 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord;
# endif
#endif
TinyIRReceiverControl.Flags);
#if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
handleReceivedTinyIRData();
#endif
} else {
// not finished yet
@ -416,6 +426,17 @@ bool isTinyReceiverIdle() {
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
}
/*
* Checks if IR_RECEIVE_PIN is connected and high
* @return true, if IR Receiver is attached
*/
bool isIRReceiverAttachedForTinyReceiver() {
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.
}
/**
* Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode.
* Then call enablePCIInterruptForTinyReceiver()
@ -429,27 +450,22 @@ bool initPCIInterruptForTinyReceiver() {
return enablePCIInterruptForTinyReceiver();
}
#if defined(USE_FAST_PROTOCOL)
void printTinyReceiverResultMinimal(Print *aSerial, uint16_t aCommand, uint8_t aFlags)
#else
void printTinyReceiverResultMinimal(Print *aSerial, uint8_t aAddress, uint8_t aCommand, uint8_t aFlags)
#endif
{
void printTinyReceiverResultMinimal(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
// 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(aAddress, HEX);
aSerial->print(TinyIRReceiverData.Address, HEX);
aSerial->print(F(" C=0x"));
#endif
aSerial->print(aCommand, HEX);
if (aFlags == IRDATA_FLAGS_IS_REPEAT) {
aSerial->print(TinyIRReceiverData.Command, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
aSerial->print(F(" R"));
}
#if !defined(DISABLE_PARITY_CHECKS)
if (aFlags == IRDATA_FLAGS_PARITY_FAILED) {
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
aSerial->print(F(" P"));
}
#endif

View File

@ -19,7 +19,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2022-2023 Armin Joachimsmeyer
* Copyright (c) 2022-2024 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -60,6 +60,10 @@
* @{
*/
#if !defined(IR_SEND_PIN)
#warning "IR_SEND_PIN is not defined, so it is set to 3"
#define IR_SEND_PIN 3
#endif
/*
* Generate 38 kHz IR signal by bit banging
*/
@ -101,12 +105,13 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) {
}
/*
* Send NEC with 16 bit command, even if aCommand < 0x100
* 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) {
void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
@ -114,13 +119,10 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast
unsigned long tStartOfFrameMillis = millis();
sendMark(aSendPin, NEC_HEADER_MARK);
#if !defined(ENABLE_NEC2_REPEATS)
if (tNumberOfCommands < aNumberOfRepeats + 1) {
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250
} else
#endif
{
} else {
// send header
delayMicroseconds(NEC_HEADER_SPACE);
LongUnion tData;
@ -154,15 +156,16 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast
}
/*
* Send NEC with 8 or 16 bit address or data depending on the values of aAddress and aCommand.
* 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) {
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
@ -170,13 +173,10 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
unsigned long tStartOfFrameMillis = millis();
sendMark(aSendPin, NEC_HEADER_MARK);
#if !defined(ENABLE_NEC2_REPEATS)
if (tNumberOfCommands < aNumberOfRepeats + 1) {
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250
} else
#endif
{
} else {
// send header
delayMicroseconds(NEC_HEADER_SPACE);
LongUnion tData;
@ -224,6 +224,63 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
}
}
/*
* 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);
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);
}
}
}
}
/*
* LSB first, send header, command, inverted command and stop bit
*/

View File

@ -63,13 +63,15 @@
// It might be that this only happens over IR and not on the datalink protocol
// You can choose to support this or not:
// Alt 1: Mode with gaps between frames
// Set RECORD_GAP_MICROS to at least 16000 to accommodate the unusually long 3. start space
// Can only receive single messages and back to back repeats will result in overflow
// Mode 1: Mode with gaps between frames
// Set RECORD_GAP_MICROS to at least 16000 to accept the unusually long 3. start space
// Can only receive single messages. Back to back repeats will result in overflow
// Alt 2: Break at start mode
// Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to 13000 to treat the 3. start space as a gap between messages
// The start of a transmission will result in a dummy decode with 0 bits data followed by the actual messages
// Mode 2: Break at start mode
// Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to less than 15000
// to treat the 3. start space of 15.5 ms as a gap between messages, which makes decoding easier :-).
// The receiving of a transmission will then result in a dummy decode of the first 2 start bits with 0 bits data
// followed by a 15.5 ms gap and a data frame with one start bit (originally sent as 4. start bit).
// If the receiver is not resumed within a ms or so, partial messages will be decoded
// Debug printing in the wrong place is very likely to break reception
// Make sure to check the number of bits to filter dummy and incomplete messages
@ -77,27 +79,29 @@
// !!! We assume that the real implementations never set the official first header bit to anything other than 0 !!!
// !!! We therefore use 4 start bits instead of the specified 3 and in turn ignore the first header bit of the specification !!!
// IR messages are 16 bits long and datalink messages have different lengths
// IR messages are 16 bits long. Datalink messages have different lengths.
// This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length
// Header data with more than 16 bits is stored in decodedIRData.extra
// B&O is a pulse distance protocol, but it has 3 bit values 0, 1 and (equal/repeat) as well as a special start and trailing bit.
//
// MSB first, 4 start bits + 8 to 16? bit address + 8 bit command + 1 special trailing bit + 1 stop bit.
// Address can be longer than 8 bit.
/*
* Options for this decoder
*
*/
//#define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory.
#define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory. Enabled by default, see https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1181
//#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory.
#if defined(DECODE_BEO)
# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
# if RECORD_GAP_MICROS > 13000
#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to 1300 by "#define RECORD_GAP_MICROS 13000"
# if RECORD_GAP_MICROS > 15000
#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 13000"
# endif
# else
# if RECORD_GAP_MICROS < 16000
#error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 1600 by "#define RECORD_GAP_MICROS 16000"
#error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 16000 by "#define RECORD_GAP_MICROS 16000"
# endif
# endif
#endif
@ -288,9 +292,9 @@ static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
bool IRrecv::decodeBangOlufsen() {
#if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
if (decodedIRData.rawDataPtr->rawlen != 6 && decodedIRData.rawDataPtr->rawlen < 36) { // 16 bits minimum
if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 36) { // 16 bits minimum
#else
if (decodedIRData.rawDataPtr->rawlen < 44) { // 16 bits minimum
if (decodedIRData.rawlen < 44) { // 16 bits minimum
#endif
return false;
}
@ -306,21 +310,21 @@ bool IRrecv::decodeBangOlufsen() {
uint8_t tBitNumber = 0;
BEO_TRACE_PRINT(F("Pre gap: "));
BEO_TRACE_PRINT(decodedIRData.rawDataPtr->rawbuf[0] * 50);
BEO_TRACE_PRINT(decodedIRData.initialGap * 50);
BEO_TRACE_PRINT(F(" raw len: "));
BEO_TRACE_PRINTLN(decodedIRData.rawDataPtr->rawlen);
BEO_TRACE_PRINTLN(decodedIRData.rawlen);
#if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
/*
* Check if we have the AGC part of the first frame in a row
* Check if we have the AGC part of the first frame, i.e. start bit 1 and 2.
*/
if (decodedIRData.rawDataPtr->rawlen == 6) {
if (decodedIRData.rawlen == 6) {
if ((matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_IR_MARK)
|| matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_DATALINK_MARK))
&& (matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK)
|| matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_DATALINK_MARK))) {
BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_TRACE_PRINTLN(F("B&O: AGC only part detected"));
BEO_TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected"));
} else {
return false; // no B&O protocol
}
@ -328,18 +332,18 @@ bool IRrecv::decodeBangOlufsen() {
/*
* Check if leading gap is trailing bit of first frame
*/
if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[0], BEO_PULSE_LENGTH_START_BIT)) {
if (!matchSpace(decodedIRData.initialGap, BEO_PULSE_LENGTH_START_BIT)) {
BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_TRACE_PRINTLN(F(": Leading gap is wrong")); // Leading gap is trailing bit of first frame
return false; // no B&O protocol
}
if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_IR_MARK)) {
#if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
# if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
protocolMarkLength = BEO_IR_MARK;
} else if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_DATALINK_MARK)) {
protocolMarkLength = BEO_DATALINK_MARK;
#endif
# endif
} else {
BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_TRACE_PRINTLN(F(": mark length is wrong"));
@ -347,10 +351,10 @@ bool IRrecv::decodeBangOlufsen() {
}
// skip first zero header bit
for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawDataPtr->rawlen; tRawBufferMarkIndex += 2) {
for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
#else
for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawDataPtr->rawlen; tRawBufferMarkIndex += 2) {
#endif
for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) {
#endif // defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
uint16_t markLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex];
uint16_t spaceLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex + 1];
@ -379,11 +383,11 @@ bool IRrecv::decodeBangOlufsen() {
} else {
if (tPulseNumber == 3) {
if (matchMark(markLength, BEO_IR_MARK)) {
#if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
# if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
protocolMarkLength = BEO_IR_MARK;
} else if (matchMark(markLength, BEO_DATALINK_MARK)) {
protocolMarkLength = BEO_DATALINK_MARK;
#endif
# endif
} else {
BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_DEBUG_PRINTLN(F(": 4. (start) mark length is wrong"));
@ -399,7 +403,7 @@ bool IRrecv::decodeBangOlufsen() {
}
}
} else {
#endif
#endif // !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
/*
* Decode header / data
@ -425,7 +429,7 @@ bool IRrecv::decodeBangOlufsen() {
break;
}
#if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
if (tRawBufferMarkIndex >= decodedIRData.rawDataPtr->rawlen - 3) { // (rawlen - 3) is index of trailing bit mark
if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of trailing bit mark
BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_DEBUG_PRINTLN(F(": End of buffer, but no trailing bit detected"));
return false;
@ -466,7 +470,7 @@ bool IRrecv::decodeBangOlufsen() {
/*
* Check for last bit after decoding it
*/
if (tRawBufferMarkIndex >= decodedIRData.rawDataPtr->rawlen - 3) { // (rawlen - 3) is index of last bit mark
if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of last bit mark
BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN));
BEO_TRACE_PRINTLN(F(": Last bit reached"));
break;

View File

@ -30,10 +30,10 @@
//
// Support for Bose Wave Radio CD initially provided by https://github.com/uvotguy.
//
// As seen on my trusty oscilloscope, there is no repeat code. Instead, when I
// As seen on my oscilloscope, there is no repeat code. Instead, when I
// press and hold a button on my remote, it sends a command, makes a 51.2ms space,
// and resends the command, etc, etc.
// LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit.
// and resends the command again, and so on.
// 38 kHz, LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit.
#define BOSEWAVE_BITS 16 // Command and inverted command
#define BOSEWAVE_HEADER_MARK 1014 // 1014 are 39 clock periods (I counted 3 times!)
@ -68,10 +68,10 @@ bool IRrecv::decodeBoseWave() {
}
// Check we have enough data +4 for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * BOSEWAVE_BITS) + 4) {
if (decodedIRData.rawlen != (2 * BOSEWAVE_BITS) + 4) {
IR_DEBUG_PRINT(F("Bose: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}

View File

@ -156,10 +156,10 @@ bool IRrecv::decodeDenon() {
// we have no start bit, so check for the exact amount of data bits
// Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != (2 * DENON_BITS) + 2) {
if (decodedIRData.rawlen != (2 * DENON_BITS) + 2) {
IR_DEBUG_PRINT(F("Denon: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 32"));
return false;
}
@ -189,7 +189,7 @@ bool IRrecv::decodeDenon() {
decodedIRData.command &= 0xFF;
// Check for (auto) repeat
if (decodedIRData.rawDataPtr->rawbuf[0] < ((DENON_AUTO_REPEAT_DISTANCE + (DENON_AUTO_REPEAT_DISTANCE / 4)) / MICROS_PER_TICK)) {
if (decodedIRData.initialGap < ((DENON_AUTO_REPEAT_DISTANCE + (DENON_AUTO_REPEAT_DISTANCE / 4)) / MICROS_PER_TICK)) {
repeatCount++;
if (repeatCount > 1) { // skip first auto repeat
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
@ -280,7 +280,7 @@ void IRsend::sendSharp(uint16_t aAddress, uint16_t aCommand) {
bool IRrecv::decodeDenonOld(decode_results *aResults) {
// Check we have the right amount of data
if (decodedIRData.rawDataPtr->rawlen != 1 + 2 + (2 * DENON_BITS) + 1) {
if (decodedIRData.rawlen != 1 + 2 + (2 * DENON_BITS) + 1) {
return false;
}

View File

@ -23,8 +23,8 @@
* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L175
* sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros,
* unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
* unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, bool aMSBFirst,
* bool aSendStopBit, unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
* unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, uint8_t aFlags,
* unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
*
@ -155,16 +155,14 @@ bool IRrecv::decodeDistanceWidth() {
/*
* Accept only protocols with at least 8 bits
*/
if (decodedIRData.rawDataPtr->rawlen < (2 * 8) + 4) {
if (decodedIRData.rawlen < (2 * 8) + 4) {
IR_DEBUG_PRINT(F("PULSE_DISTANCE_WIDTH: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is less than 20"));
return false;
}
uint_fast8_t i;
// Reset duration array
memset(tDurationArray, 0, DURATION_ARRAY_SIZE);
@ -172,7 +170,7 @@ bool IRrecv::decodeDistanceWidth() {
/*
* Count number of mark durations up to 49 ticks. Skip leading start and trailing stop bit.
*/
for (i = 3; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) {
auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (tDurationTicks < DURATION_ARRAY_SIZE) {
tDurationArray[tDurationTicks]++; // count duration if less than DURATION_ARRAY_SIZE (50)
@ -219,7 +217,7 @@ bool IRrecv::decodeDistanceWidth() {
* Count number of space durations. Skip leading start and trailing stop bit.
*/
tIndexOfMaxDuration = 0;
for (i = 4; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) {
for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) {
auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
if (tDurationTicks < DURATION_ARRAY_SIZE) {
tDurationArray[tDurationTicks]++;
@ -231,7 +229,7 @@ bool IRrecv::decodeDistanceWidth() {
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.print(F("Space "));
Serial.print(tDurationTicks * MICROS_PER_TICK);
Serial.print(F(" is longer than "));
Serial.print(F(" is longer than maximum "));
Serial.print(DURATION_ARRAY_SIZE * MICROS_PER_TICK);
Serial.print(F(" us. Index="));
Serial.println(i);
@ -284,9 +282,12 @@ bool IRrecv::decodeDistanceWidth() {
Serial.print(F(", "));
Serial.println(tSpaceTicksShort * MICROS_PER_TICK);
#endif
uint8_t tStartIndex = 3;
// skip leading start bit for decoding.
uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 1;
#if RAW_BUFFER_LENGTH <= 508
uint_fast8_t tNumberOfBits;
#else
uint16_t tNumberOfBits;
#endif
tNumberOfBits = (decodedIRData.rawlen / 2) - 1;
if (tSpaceTicksLong > 0 && tMarkTicksLong == 0) {
// For PULSE_DISTANCE a stop bit is mandatory, for PULSE_WIDTH it is not required!
tNumberOfBits--; // Correct for stop bit
@ -320,6 +321,7 @@ bool IRrecv::decodeDistanceWidth() {
unsigned int tMarkMicrosShort = tMarkTicksShort * MICROS_PER_TICK;
unsigned int tMarkMicrosLong = tMarkTicksLong * MICROS_PER_TICK;
unsigned int tSpaceMicrosLong = tSpaceTicksLong * MICROS_PER_TICK;
IRRawlenType tStartIndex = 3; // skip leading start bit for decoding.
for (uint_fast8_t i = 0; i <= tNumberOfAdditionalArrayValues; ++i) {
uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;

View File

@ -96,13 +96,13 @@ void IRsend::sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
bool IRrecv::decodeFAST() {
// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size
// uint_fast8_t tRawlen = decodedIRData.rawlen; // Using a local variable does not improve code size
// Check we have the right amount of data (36). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * FAST_BITS) + 4)) {
if (decodedIRData.rawlen != ((2 * FAST_BITS) + 4)) {
IR_DEBUG_PRINT(F("FAST: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}

View File

@ -118,26 +118,26 @@ void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe
bool IRrecv::decodeJVC() {
// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size
// uint_fast8_t tRawlen = decodedIRData.rawlen; // Using a local variable does not improve code size
// Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark.
// +4 is for first frame, +2 is for repeats
if (decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 4)) {
if (decodedIRData.rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawlen != ((2 * JVC_BITS) + 4)) {
IR_DEBUG_PRINT(F("JVC: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 34 or 36"));
return false;
}
if (decodedIRData.rawDataPtr->rawlen == ((2 * JVC_BITS) + 2)) {
if (decodedIRData.rawlen == ((2 * JVC_BITS) + 2)) {
/*
* Check for repeat
* Check leading space and first and last mark length
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK))
if (decodedIRData.initialGap < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK))
&& matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_BIT_MARK)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen - 1], JVC_BIT_MARK)) {
&& matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawlen - 1], JVC_BIT_MARK)) {
/*
* We have a repeat here, so do not check for start bit
*/
@ -231,6 +231,7 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) {
/**
* With Send sendJVCMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte.
* Use bitreverse32Bit().
* Or write it as one binary string and reverse/mirror it.
* Example:
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.

View File

@ -75,22 +75,22 @@
*/
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Panasonic
// http://www.hifi-remote.com/johnsfine/DecodeIR.html#Kaseikyo
// LSB first
// The first two (8-bit) bytes contains the vendor code.
// The next 4 bit is VendorID parity.
// The last byte is parity (XOR) of the 3 bytes before.
// There are multiple interpretations of the next fields:
// IRP: {37k,432}<1,-1|1,-3>(8,-4,M:8,N:8,X:4,D:4,S:8,F:8,G:8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4}
// 1. interpretation: After the vendor code, the next byte is 4 bit VendorID parity and 4 bit Device and Subdevice
// The 5th byte is the function and the last (6.th) byte is xor of the three bytes before it.
// 0_______ 1_______ 2______ 3_______ 4_______ 5
// 1. interpretation: 4 bit Device, 8 bitSubdevice and 8 bit function.
// 0_______ 1_______ 2______ 3_______ 4_______ 5_______
// 01234567 89ABCDEF 01234567 01234567 01234567 01234567
// 01000000 00100100 Dev____ Sub_Dev_ Fun____ XOR( B2, B3, B4) - showing Panasonic vendor code 0x2002
// 01000000 00100100 0110Dev_ Sub_Dev_ Fun____ XOR( B2, B3, B4) - Byte 0,1 and vendor parity showing Panasonic vendor code 0x2002.
// 1. interpretation: <start bit><VendorID:16><VendorID parity:4><Device:4><Subdevice:8><Function:8><Parity:8><stop bit>
// see: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152
//
// 2. interpretation: LSB first, start bit + 16 VendorID + 4 VendorID parity + 4 Genre1 + 4 Genre2 + 10 Command + 2 ID + 8 Parity + stop bit
// 2. interpretation (Flipper Zero style): <start bit><VendorID:16><VendorID parity:4><Genre1:4><Genre2:4><Command:10><ID:2><Parity:8><stop bit>
// see: https://www.mikrocontroller.net/articles/IRMP_-_english#KASEIKYO
// 32 bit raw data LSB is VendorID parity.
//
// We reduce it to: IRP: {37k,432}<1,-1|1,-3>(8,-4,V:16,X:4,D:4,S:8,F:8,(X^D^S^F):8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4}
// start bit + 16 VendorID + 4 VendorID parity + 12 Address + 8 Command + 8 Parity of VendorID parity, Address and Command + stop bit
// Implemented is Samsung style: <start bit><VendorID:16><VendorID parity:4><Address:12><Command:8><Parity of VendorID parity, Address and Command:8><stop bit>
// which is derived from Samsung remotes and may not be optimal for Denon kind of Kaseikyo protokol usage.
//
#define KASEIKYO_VENDOR_ID_BITS 16
#define KASEIKYO_VENDOR_ID_PARITY_BITS 4
@ -127,7 +127,7 @@ KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK,
************************************/
/**
* Address can be interpreted as sub-device << 8 + device
* Address can be interpreted as sub-device << 4 + 4 bit device
*/
void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aVendorCode) {
// Set IR carrier frequency
@ -140,9 +140,9 @@ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumb
#if __INT_WIDTH__ < 32
LongUnion tSendValue;
// Compute parity
tSendValue.UWord.LowWord = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble to parity
tSendValue.UWord.LowWord = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble with vendor parity
tSendValue.UBytes[2] = aCommand;
tSendValue.UBytes[3] = aCommand ^ tSendValue.UBytes[0] ^ tSendValue.UBytes[1]; // Parity
tSendValue.UBytes[3] = aCommand ^ tSendValue.UBytes[0] ^ tSendValue.UBytes[1]; // 8 bit parity of 3 bytes command, address and vendor parity
IRRawDataType tRawKaseikyoData[2];
tRawKaseikyoData[0] = (uint32_t) tSendValue.UWord.LowWord << 16 | aVendorCode; // LSB of tRawKaseikyoData[0] is sent first
tRawKaseikyoData[1] = tSendValue.UWord.HighWord;
@ -200,10 +200,10 @@ bool IRrecv::decodeKaseikyo() {
decode_type_t tProtocol;
// Check we have enough data (96 + 4) 4 for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != ((2 * KASEIKYO_BITS) + 4)) {
if (decodedIRData.rawlen != ((2 * KASEIKYO_BITS) + 4)) {
IR_DEBUG_PRINT(F("Kaseikyo: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 100"));
return false;
}

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2023 Darryl Smith, Armin Joachimsmeyer
* Copyright (c) 2017-2024 Darryl Smith, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -124,7 +124,7 @@ LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERI
* Start of send and decode functions
************************************/
/*
* Send special LG2 repeat not used yet
* Send special LG2 repeat - not used internally
*/
void IRsend::sendLG2Repeat() {
enableIROut (LG_KHZ); // 38 kHz
@ -184,30 +184,30 @@ bool IRrecv::decodeLG() {
*/
// Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
if (decodedIRData.rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawlen != 4)) {
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 60 or 4"));
return false;
}
// Check header "mark" this must be done for repeat and data
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG_HEADER_MARK)) {
if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) {
if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) {
tProtocol = LG2;
tHeaderSpace = LG2_HEADER_SPACE;
} else {
#if defined(LOCAL_DEBUG)
Serial.print(F("LG: "));
Serial.println(F("Header mark is wrong"));
#endif
return false;
} else {
tProtocol = LG2;
tHeaderSpace = LG2_HEADER_SPACE;
return false; // neither LG nor LG2 header
}
}
// Check for repeat - here we have another header space length
if (decodedIRData.rawDataPtr->rawlen == 4) {
if (decodedIRData.rawlen == 4) {
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;

View File

@ -45,15 +45,16 @@
// from LEGO Power Functions RC Manual 26.02.2010 Version 1.20
// https://github.com/jurriaan/Arduino-PowerFunctions/raw/master/LEGO_Power_Functions_RC_v120.pdf
// https://oberguru.net/elektronik/ir/codes/lego_power_functions_train.lircd.conf
// For original LEGO receiver see: https://www.philohome.com/pfrec/pfrec.htm and https://www.youtube.com/watch?v=KCM4Ug1bPrM
//
// To ensure correct detection of IR messages six 38 kHz cycles are transmitted as mark.
// Low bit consists of 6 cycles of IR and 10 “cycles” of pause,
// high bit of 6 cycles IR and 21 “cycles” of pause and start bit of 6 cycles IR and 39 “cycles” of pause.
// Low bit consists of 6 cycles of IR and 10 <EFBFBD>cycles<EFBFBD> of pause,
// high bit of 6 cycles IR and 21 <EFBFBD>cycles<EFBFBD> of pause and start bit of 6 cycles IR and 39 <20>cycles<65> of pause.
// Low bit range 316 - 526 us
// High bit range 526 947 us
// Start/stop bit range 947 1579 us
// High bit range 526 <EFBFBD> 947 us
// Start/stop bit range 947 <EFBFBD> 1579 us
// If tm is the maximum message length (16ms) and Ch is the channel number, then
// The delay before transmitting the first message is: (4 Ch)*tm
// The delay before transmitting the first message is: (4 <EFBFBD> Ch)*tm
// The time from start to start for the next 2 messages is: 5*tm
// The time from start to start for the following messages is: (6 + 2*Ch)*tm
// Supported Devices
@ -186,7 +187,7 @@ bool IRrecv::decodeLegoPowerFunctions() {
/*
* Check for autorepeat (should happen 4 times for one press)
*/
if (decodedIRData.rawDataPtr->rawbuf[0] < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) {
if (decodedIRData.initialGap < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) {
decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
}
decodedIRData.address = tToggleEscapeChannel;

View File

@ -151,10 +151,10 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) {
bool IRrecv::decodeMagiQuest() {
// Check we have the right amount of data, magnitude and ID bits and 8 start bits + 0 stop bit
if (decodedIRData.rawDataPtr->rawlen != (2 * MAGIQUEST_BITS)) {
if (decodedIRData.rawlen != (2 * MAGIQUEST_BITS)) {
IR_DEBUG_PRINT(F("MagiQuest: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 112"));
return false;
}

View File

@ -33,9 +33,9 @@
#define _IR_NEC_HPP
#if defined(DEBUG) && !defined(LOCAL_DEBUG)
#define LOCAL_DEBUG
#define LOCAL_DEBUG // IR_DEBUG_PRINT is a real print function here. Add local debug output.
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
//#define LOCAL_DEBUG // This enables debug output only for this file. IR_DEBUG_PRINT is still a void function here.
#endif
/** \addtogroup Decoder Decoders and encoders for different protocols
@ -71,17 +71,20 @@
*/
// http://www.hifi-remote.com/wiki/index.php/NEC
// https://www.sbprojects.net/knowledge/ir/nec.php
// for Apple see https://en.wikipedia.org/wiki/Apple_Remote - Fixed address 0x87EE, 8 bit device ID, 7 bit command, 1 bit parity - untested!
// ONKYO like NEC but 16 independent address and command bits
// APPLE like ONKYO with special NEC repeat but with constant address of 0x87EE and and 16 bit command interpreted as MSB = 8 bit device ID, LSB = 8 bit command
// PIONEER (not implemented) is NEC2 with 40 kHz
// LSB first, 1 start bit + 16 bit address (or 8 bit address and 8 bit inverted address) + 8 bit command + 8 bit inverted command + 1 stop bit.
// NEC: LSB first, <start bit><address:16> (or <address:8><inverted address:8>) <command:8><inverted command:8><stop bit>.
// ONKYO like NEC but 16 independent address and command bits: <start bit><address:16><command:16><stop bit>
// Standard NEC sends a special fixed repeat frame.
// NEC2 sends the same full frame after the 110 ms. I have a DVD remote with NEC2.
// NEC and NEC 2 only differ in the repeat frames, so the protocol can only be detected correctly after the first repeat.
// PIONEER (not implemented) is NEC2 with 40 kHz
//
// For Apple see https://en.wikipedia.org/wiki/Apple_Remote - <start bit><0x87EE:16><device ID:8><command:7><parity><stop bit> - not implemented!
// The parity is not implemented, so we get: <start bit><0x87EE:16><device ID:8><command:8><stop bit>
//
// IRP notation:
// IRP: NEC {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m,(16,-4,1,^108m)*) ==> "*" means send special repeat frames o ore more times
// IRP: NEC2 {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m)+ ==> "+" means send frame 1 or more times (special repeat is missing here!)
// Interpretation of IRP notation:
// {38.0k,564} ==> 38.0k -> Frequency , 564 -> unit in microseconds (we use 560), no "msb", so "lsb" is assumed
// <1,-1|1,-3> ==> Zero is 1 unit mark and space | One is 1 unit mark and 3 units space
// 16,-8 ==> Start bit durations
@ -137,7 +140,7 @@ void IRsend::sendNECRepeat() {
}
/**
* Static function for sending special repeat frame.
* Static function variant of IRsend::sendNECRepeat
* For use in ProtocolConstants. Saves up to 250 bytes compared to a member function.
*/
void sendNECSpecialRepeat() {
@ -168,8 +171,7 @@ uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aComma
/**
* NEC Send frame and special repeats
* There is NO delay after the last sent repeat!
* @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space
* will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction().
* @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction().
*/
void IRsend::sendNEC(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
sendPulseDistanceWidth(&NECProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats);
@ -199,14 +201,13 @@ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumber
* There is NO delay after the last sent repeat!
* https://en.wikipedia.org/wiki/Apple_Remote
* https://gist.github.com/darconeous/4437f79a34e3b6441628
* @param aAddress is the DeviceId*
* @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space
* will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction().
*/
void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
LongUnion tRawData;
// Address 16 bit LSB first
// Address 16 bit LSB first fixed value of 0x87EE
tRawData.UWord.LowWord = APPLE_ADDRESS;
// send Apple code and then 8 command bits LSB first
@ -217,7 +218,7 @@ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberO
}
/*
* Sends NEC1 protocol
* Sends NEC protocol
* @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space
* will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction().
*/
@ -235,10 +236,10 @@ bool IRrecv::decodeNEC() {
* Next try the decode
*/
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) {
if (decodedIRData.rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawlen != 4)) {
IR_DEBUG_PRINT(F("NEC: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 68 or 4"));
return false;
}
@ -249,7 +250,7 @@ bool IRrecv::decodeNEC() {
}
// Check for repeat - here we have another header space length
if (decodedIRData.rawDataPtr->rawlen == 4) {
if (decodedIRData.rawlen == 4) {
if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_REPEAT_HEADER_SPACE)
&& matchMark(decodedIRData.rawDataPtr->rawbuf[3], NEC_BIT_MARK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
@ -326,6 +327,7 @@ bool IRrecv::decodeNEC() {
checkForRepeatSpaceTicksAndSetFlag(NEC_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK);
if (decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
decodedIRData.protocol = NEC2;
decodedIRData.flags |= IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT;
}
return true;
}
@ -401,6 +403,7 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) {
/**
* With Send sendNECMSB() you can send your old 32 bit codes.
* To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte.
* Use bitreverse32Bit().
* Or write it as one binary string and reverse/mirror it.
* Example:
* 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3.

View File

@ -93,7 +93,7 @@ void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) {
bool IRrecv::decodeWhynter() {
// Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark.
if (decodedIRData.rawDataPtr->rawlen != (2 * WHYNTER_BITS) + 4) {
if (decodedIRData.rawlen != (2 * WHYNTER_BITS) + 4) {
return false;
}
if (!checkHeader(&WhynterProtocolConstants)) {

View File

@ -174,7 +174,7 @@ void IRsend::sendPronto(const char *str, int_fast8_t aNumberOfRepeats) {
void IRsend::sendPronto_PF(uint_farptr_t str, int_fast8_t aNumberOfRepeats) {
size_t len = strlen_PF(str);
char work[len + 1];
strncpy_PF(work, str, len);
strcpy_PF(work, str); // We know that string including terminating character fits in work
sendPronto(work, aNumberOfRepeats);
}
@ -182,15 +182,18 @@ void IRsend::sendPronto_PF(uint_farptr_t str, int_fast8_t aNumberOfRepeats) {
void IRsend::sendPronto_P(const char *str, int_fast8_t aNumberOfRepeats) {
size_t len = strlen_P(str);
char work[len + 1];
strncpy_P(work, str, len);
strcpy_P(work, str);
sendPronto(work, aNumberOfRepeats);
}
#endif
/*
* Copy flash data to ram buffer in stack
*/
void IRsend::sendPronto(const __FlashStringHelper *str, int_fast8_t aNumberOfRepeats) {
size_t len = strlen_P(reinterpret_cast<const char*>(str));
char work[len + 1];
strncpy_P(work, reinterpret_cast<const char*>(str), len);
strcpy_P(work, reinterpret_cast<const char*>(str));
return sendPronto(work, aNumberOfRepeats);
}
@ -256,10 +259,10 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFreque
aSerial->print(F("char prontoData[] = \""));
dumpNumber(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken);
dumpNumber(aSerial, toFrequencyCode(aFrequencyHertz));
dumpNumber(aSerial, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
dumpNumber(aSerial, (decodedIRData.rawlen + 1) / 2);
dumpNumber(aSerial, 0);
uint16_t timebase = toTimebase(aFrequencyHertz);
compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, timebase); // skip leading space
compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space
aSerial->println("\";");
}
@ -326,9 +329,9 @@ size_t IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) {
size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken);
size += dumpNumber(aString, toFrequencyCode(frequency));
size += dumpNumber(aString, (decodedIRData.rawDataPtr->rawlen + 1) / 2);
size += dumpNumber(aString, (decodedIRData.rawlen + 1) / 2);
size += dumpNumber(aString, 0);
size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1,
size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1,
timebase); // skip leading space
return size;

View File

@ -160,11 +160,11 @@ bool IRrecv::decodeRC5() {
initBiphaselevel(1, RC5_UNIT); // Skip gap space
// Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark.
if (decodedIRData.rawDataPtr->rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawDataPtr->rawlen) {
if (decodedIRData.rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawlen) {
// no debug output, since this check is mainly to determine the received protocol
IR_DEBUG_PRINT(F("RC5: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not between 9 and 15"));
return false;
}
@ -179,7 +179,7 @@ bool IRrecv::decodeRC5() {
/*
* Get data bits - MSB first
*/
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) {
// get next 2 levels and check for transition
uint8_t tStartLevel = getBiphaselevel();
uint8_t tEndLevel = getBiphaselevel();
@ -396,10 +396,10 @@ bool IRrecv::decodeRC6() {
uint32_t tDecodedRawData = 0;
// Check we have the right amount of data (). The +3 for initial gap, start bit mark and space
if (decodedIRData.rawDataPtr->rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawDataPtr->rawlen) {
if (decodedIRData.rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawlen) {
IR_DEBUG_PRINT(F("RC6: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not between 15 and 25"));
return false;
}
@ -428,7 +428,7 @@ bool IRrecv::decodeRC6() {
return false;
}
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) {
for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) {
uint8_t tStartLevel; // start level of coded bit
uint8_t tEndLevel; // end level of coded bit

View File

@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
* Copyright (c) 2017-2023 Darryl Smith, Armin Joachimsmeyer
* Copyright (c) 2017-2024 Darryl Smith, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -63,7 +63,7 @@
Sum: 68750
*/
/*
* Samsung repeat frame can be the original frame again or a special repeat frame,
* Samsung repeat frame can be the original frame again or a special short repeat frame,
* then we call the protocol SamsungLG. They differ only in the handling of repeat,
* so we can not decide for the first frame which protocol is used.
*/
@ -72,6 +72,12 @@
// https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG48
// LSB first, 1 start bit + 16 bit address + 16 or 32 bit data + 1 stop bit.
// Here https://forum.arduino.cc/t/klimaanlage-per-ir-steuern/1051381/10 the address (0xB24D) is also 8 bits and then 8 inverted bits
//
// Here https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18
// Address is 8 bit + same 8 bit if command is 8 bit and ~8 bit.
//
// So we assume 8 bit address, if command is 8 bit and ~8 bit!
//
// IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,1,^110)+ ==> 8 bit + 8 bit inverted data - Samsung32
// IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:16,1,^110)+ ==> 16 bit data - still Samsung32
// IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,G:8,~G:8,1,^110)+ ==> 2 x (8 bit + 8 bit inverted data) - Samsung48
@ -84,7 +90,7 @@
// except SAMSUNG_HEADER_MARK, values are like NEC
#define SAMSUNG_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0
#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4500 | 180
#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4500 | 180 periods
#define SAMSUNG_HEADER_SPACE (8 * SAMSUNG_UNIT) // 4500
#define SAMSUNG_BIT_MARK SAMSUNG_UNIT
#define SAMSUNG_ONE_SPACE (3 * SAMSUNG_UNIT) // 1690 | 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0
@ -93,13 +99,16 @@
#define SAMSUNG_AVERAGE_DURATION 55000 // SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones
#define SAMSUNG_REPEAT_DURATION (SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + SAMSUNG_BIT_MARK + SAMSUNG_ZERO_SPACE + SAMSUNG_BIT_MARK)
#define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
#define SAMSUNG_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD - SAMSUNG_AVERAGE_DURATION)
#define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_DISTANCE + (SAMSUNG_REPEAT_DISTANCE / 4)) // Just a guess
#define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess
// 19 byte RAM
struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK,
SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
(SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat };
(SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
struct PulseDistanceWidthProtocolConstants SamsungLGProtocolConstants = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK,
SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
(SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat };
/************************************
* Start of send and decode functions
************************************/
@ -119,7 +128,8 @@ void IRsend::sendSamsungLGRepeat() {
}
/**
* Static function for sending special repeat frame.
* Like above, but implemented as a static function
* Used for sending special repeat frame.
* For use in ProtocolConstants. Saves up to 250 bytes compared to a member function.
*/
void sendSamsungLGSpecialRepeat() {
@ -147,24 +157,35 @@ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNu
tRawData.UByte.MidHighByte = aCommand;
tRawData.UByte.HighByte = ~aCommand;
sendPulseDistanceWidth(&SamsungProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats);
sendPulseDistanceWidth(&SamsungLGProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats);
}
/**
* Here we send Samsung32
* If we get a command < 0x100, we send command and then ~command
* If we get an address < 0x100, we send 8 bit address and then the same 8 bit address again, this makes it flipper IRDB compatible
* !!! Be aware, that this is flexible, but makes it impossible to send e.g. 0x0042 as 16 bit value!!!
* To force send 16 bit address, use: sendSamsung16BitAddressAndCommand().
* @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent
*/
void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
// send 16 bit address
LongUnion tSendValue;
tSendValue.UWords[0] = aAddress;
if (aAddress < 0x100) {
// This makes it flipper IRDB compatible:
// https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18
// Duplicate address byte, if address is only 8 bit
tSendValue.UBytes[1] = aAddress;
tSendValue.UBytes[0] = aAddress;
} else {
tSendValue.UWords[0] = aAddress;
}
if (aCommand < 0x100) {
// Send 8 command bits and then 8 inverted command bits LSB first
tSendValue.UBytes[2] = aCommand;
tSendValue.UBytes[3] = ~aCommand;
} else {
// Send 16 command bits
tSendValue.UWords[1] = aCommand;
@ -173,6 +194,38 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb
sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats);
}
/**
* Maybe no one needs it in the wild...
* As above, but we are able to send e.g. 0x0042 as 16 bit address
* @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent
*/
void IRsend::sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
LongUnion tSendValue;
// send 16 bit address
tSendValue.UWords[0] = aAddress;
// Send 8 command bits and then 8 inverted command bits LSB first
tSendValue.UBytes[2] = aCommand;
tSendValue.UBytes[3] = ~aCommand;
sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats);
}
/**
* Maybe no one needs it in the wild...
* As above, but we are able to send e.g. 0x0042 as 16 bit address
* @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent
*/
void IRsend::sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
LongUnion tSendValue;
// send 16 bit address
tSendValue.UWords[0] = aAddress;
// Send 16 command bits
tSendValue.UWords[1] = aCommand;
sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats);
}
/**
* Here we send Samsung48
* We send 2 x (8 bit command and then ~command)
@ -208,14 +261,19 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu
#endif
}
/*
* We cannot decode frames with 8 command bits and then 8 inverted command bits LSB and 16 bit address,
* because in this case we always assume 8 bit address.
* This is, because we did not see 8 bit command and real 16 bit address in the wild.
*/
bool IRrecv::decodeSamsung() {
// Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark
if (decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG_BITS) + 4)
&& decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG48_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 6)) {
if (decodedIRData.rawlen != ((2 * SAMSUNG_BITS) + 4) && decodedIRData.rawlen != ((2 * SAMSUNG48_BITS) + 4)
&& (decodedIRData.rawlen != 6)) {
IR_DEBUG_PRINT(F("Samsung: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 6 or 68 or 100"));
return false;
}
@ -225,11 +283,11 @@ bool IRrecv::decodeSamsung() {
}
// Check for SansungLG style repeat
if (decodedIRData.rawDataPtr->rawlen == 6) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
if (decodedIRData.rawlen == 6) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST;
decodedIRData.address = lastDecodedAddress;
decodedIRData.command = lastDecodedCommand;
decodedIRData.protocol = SAMSUNG_LG;
decodedIRData.protocol = SAMSUNGLG;
return true;
}
@ -247,7 +305,7 @@ bool IRrecv::decodeSamsung() {
tValue.ULong = decodedIRData.decodedRawData;
decodedIRData.address = tValue.UWord.LowWord;
if (decodedIRData.rawDataPtr->rawlen == (2 * SAMSUNG48_BITS) + 4) {
if (decodedIRData.rawlen == (2 * SAMSUNG48_BITS) + 4) {
/*
* Samsung48
*/
@ -289,10 +347,11 @@ bool IRrecv::decodeSamsung() {
* Samsung32
*/
if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) {
// 8 bit command protocol
// 8 bit command protocol -> assume 8 bit address
decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit
decodedIRData.address = tValue.UByte.LowByte; // assume LowByte == MidLowByte
} else {
// 16 bit command protocol
// 16 bit command protocol, address is filled above with the 16 bit value
decodedIRData.command = tValue.UWord.HighWord; // first 16 bit
}
decodedIRData.numberOfBits = SAMSUNG_BITS;
@ -348,7 +407,7 @@ bool IRrecv::decodeSAMSUNG(decode_results *aResults) {
}
// Old version with MSB first
void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
void IRsend::sendSamsungMSB(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut (SAMSUNG_KHZ);
@ -360,6 +419,9 @@ void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, data, nbits,
PROTOCOL_IS_MSB_FIRST);
}
void IRsend::sendSAMSUNG(unsigned long data, int nbits) {
sendSamsungMSB(data, nbits);
}
/** @}*/
#if defined(LOCAL_DEBUG)

View File

@ -113,16 +113,16 @@ bool IRrecv::decodeSony() {
}
// Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42
if (decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MAX) + 2
&& decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_15) + 2) {
if (decodedIRData.rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_MAX) + 2
&& decodedIRData.rawlen != (2 * SONY_BITS_15) + 2) {
IR_DEBUG_PRINT(F("Sony: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
IR_DEBUG_PRINT(decodedIRData.rawlen);
IR_DEBUG_PRINTLN(F(" is not 12, 15 or 20"));
return false;
}
if (!decodePulseDistanceWidthData(&SonyProtocolConstants, (decodedIRData.rawDataPtr->rawlen - 1) / 2, 3)) {
if (!decodePulseDistanceWidthData(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Sony: "));
Serial.println(F("Decode failed"));
@ -134,7 +134,7 @@ bool IRrecv::decodeSony() {
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
decodedIRData.command = decodedIRData.decodedRawData & 0x7F; // first 7 bits
decodedIRData.address = decodedIRData.decodedRawData >> 7; // next 5 or 8 or 13 bits
decodedIRData.numberOfBits = (decodedIRData.rawDataPtr->rawlen - 1) / 2;
decodedIRData.numberOfBits = (decodedIRData.rawlen - 1) / 2;
decodedIRData.protocol = SONY;
//Check for repeat
@ -213,7 +213,7 @@ bool IRrecv::decodeSonyMSB(decode_results *aResults) {
/**
* Old version with MSB first data
*/
void IRsend::sendSony(unsigned long data, int nbits) {
void IRsend::sendSonyMSB(unsigned long data, int nbits) {
// Set IR carrier frequency
enableIROut (SONY_KHZ);
@ -224,6 +224,9 @@ void IRsend::sendSony(unsigned long data, int nbits) {
// Old version with MSB first Data
sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST);
}
void IRsend::sendSony(unsigned long data, int nbits) {
sendSonyMSB(data, nbits);
}
/** @}*/
#if defined(LOCAL_DEBUG)

View File

@ -52,12 +52,13 @@ void enableSendPWMByTimer();
void disableSendPWMByTimer();
void timerConfigForSend(uint16_t aFrequencyKHz);
#if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) )
#define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation are independent, so it is recommended to always define SEND_PWM_BY_TIMER
// SEND_PWM_BY_TIMER is defined in IRremote.hpp line 195.
#if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) )
#define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here.
#endif
#if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For e.g ESP32 IR_SEND_PIN definition is useful
#undef IR_SEND_PIN // avoid warning below, user warning is done at IRremote.hpp
#if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For ESP32 etc. IR_SEND_PIN definition is useful
#undef IR_SEND_PIN // To avoid "warning: "IR_SEND_PIN" redefined". The user warning is done at IRremote.hpp line 202.
#endif
// Macros for enabling timers for development
@ -180,7 +181,7 @@ void disableSendPWMByTimer() {
#elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards
# if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D)
#define IR_USE_AVR_TIMER_A // use this if you use MegaTinyCore, Tone is on TCB and millis() on TCD
#define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD
//#define IR_USE_AVR_TIMER_D // use this if you use TinyCore
# endif
@ -1093,7 +1094,6 @@ void timerConfigForSend(uint16_t aFrequencyKHz) {
/**********************************************
* Uno R4 boards
* The FspTimer uses undocumented
**********************************************/
#elif defined(ARDUINO_ARCH_RENESAS)
#include "FspTimer.h"
@ -1397,6 +1397,9 @@ void timerConfigForSend(uint16_t aFrequencyKHz) {
}
# endif // defined(SEND_PWM_BY_TIMER)
/**********************************************************
* ESP8266 boards
**********************************************************/
#elif defined(ESP8266)
# if defined(SEND_PWM_BY_TIMER)
#error "No support for hardware PWM generation for ESP8266"
@ -1411,7 +1414,7 @@ void timerEnableReceiveInterrupt() {
timer1_attachInterrupt(&IRReceiveTimerInterruptHandler); // enables interrupt too
}
void timerDisableReceiveInterrupt() {
timer1_detachInterrupt(); // disables interrupt too }
timer1_detachInterrupt(); // disables interrupt too
}
void timerConfigForReceive() {
@ -1435,9 +1438,8 @@ void timerConfigForReceive() {
// the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code.
hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive()
# if !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL)
#define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL)
#define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
# endif
void timerEnableReceiveInterrupt() {
@ -1470,6 +1472,7 @@ void timerDisableReceiveInterrupt() {
#undef ISR
# endif
# if !defined(DISABLE_CODE_FOR_RECEIVER) // &IRReceiveTimerInterruptHandler is referenced, but not available
void timerConfigForReceive() {
// ESP32 has a proper API to setup timers, no weird chip macros needed
// simply call the readable API versions :)
@ -1481,25 +1484,54 @@ void timerConfigForReceive() {
}
// every 50 us, autoreload = true
}
# endif
# if !defined(IR_SEND_PIN)
uint8_t sLastSendPin = 0; // To detach before attach, if already attached
# endif
# if defined(SEND_PWM_BY_TIMER)
void enableSendPWMByTimer() {
ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution
# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution
# else
ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API
# endif
}
void disableSendPWMByTimer() {
ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0);
# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
ledcWrite(SEND_LEDC_CHANNEL, 0);
# else
ledcWrite(IrSender.sendPin, 0); // New API
# endif
}
/*
* timerConfigForSend() is used exclusively by IRsend::enableIROut()
* ledcWrite since ESP 2.0.2 does not work if pin mode is set. Disable receive interrupt if it uses the same resource
* timerConfigForSend() is used exclusively by IRsend::enableIROut() (or enableHighFrequencyIROut())
* ledcWrite since ESP 2.0.2 does not work if pin mode is set.
*/
void timerConfigForSend(uint16_t aFrequencyKHz) {
ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution
# if defined(IR_SEND_PIN)
ledcAttachPin(IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // bind pin to channel
# else
ledcAttachPin(IrSender.sendPin, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // bind pin to channel
# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0)
ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution
# if defined(IR_SEND_PIN)
ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel
# else
if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){
ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194
}
ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel
sLastSendPin = IrSender.sendPin;
# endif
# else // New API here
# if defined(IR_SEND_PIN)
ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // New API
# else
if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){
ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194
}
ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // New API
sLastSendPin = IrSender.sendPin;
# endif
# endif
}
# endif // defined(SEND_PWM_BY_TIMER)