diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 95c4245c1..56e71e9f3 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -11,41 +11,22 @@ body:
**Issues are expected to lead to changes in the repository, like code or documentation improvements or bug fixes.**
If you have handling problems or questions, consider to post in [Discussions](../discussions) instead.
- # Environment
-
- - type: dropdown
- id: Board
- attributes:
- label: The type of board you are using.
- options:
- - Arduino ATmega328* board (Uno, Nano, etc.)
- - Arduino ATmega2560 board (Mega)
- - Arduino ATmega32U4 board (Leonardo, etc.)
- - Arduino ATmega4809 megaAVR board (NanoEvery)
- - Arduino SAM board (Due)
- - Arduino SAMD board (Zero, MKR*)
- - ATtiny85 board (ATTinyCore by Spence Conde)
- - Digispark board
- - ATtiny3217 board (TinyCore)
- - ESP32 board - first check https://github.com/crankyoldgit/IRremoteESP8266
- - STM32F1 board (BluePill)
- - Teensy board
- - Other - please specify below
- validations:
- required: true
-
- type: input
- id: Other_board_NAME_FQBN
- attributes:
- label: The boards name or FQBN (e.g. esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80) for unspecified board.
+ id: Board_FQBN
+ attributes:
+ label: Please specify "FQBN" (Fully Qualified Board Name).
+ It is the first line in the compiler output in the Arduino IDE 2.x.
+ E.g. "esp32:esp32:featheresp32:FlashFreq=80".
+ The FQBN starts with the core name, which is essential for bugfixing.
+ For example, at least two prominent cores are available for the Bluepill board, namely STMicroelectronics and STM32duino.
+ Without the FQBN we are most likely not able to fix the the issue.
validations:
- required: false
+ required: true
- type: input
- id: Other_board_URL
+ id: Exotic_core_URL
attributes:
- label: The board manager URL used for unspecified board.
- value: "https://"
+ label: The board manager URL used for exotic cores.
validations:
required: false
@@ -54,11 +35,11 @@ body:
attributes:
label: What IDE are you using?
options:
- - Arduino IDE
+ - Arduino 2.x IDE
+ - PlatformIO IDE
+ - Arduino 1.x IDE
- Arduino Web Editor
- - Arduino Pro IDE
- Sloeber IDE
- - PlatformIO IDE
- Other - please specify below
multiple: false
validations:
@@ -83,6 +64,7 @@ body:
- Samsung
- Sharp
- Sony
+ - Universal Pulse Distance
- Whynter
- Other - please specify below
multiple: true
@@ -107,33 +89,33 @@ body:
- label: ReceiveDemo
- label: SendRawDemo
- label: ReceiverTimingAnalysis
+ - label: ReceiveDump
- label: TinyReceiver
- label: TinySender
- label: ReceiveAndSend
- label: SimpleSender
- label: SendDemo
- - label: SendLGAirConditionerDemo
- label: UnitTest
- label: Other - please specify below
- - label: I checked, if at least one of the examples was working.
+ - label: I checked, whether at least one of the examples was working.
required: true
- type: checkboxes
id: Failed_examples
attributes:
label: Example(s) to reproduce the issue.
- description: Select only the examples which shows your error.
+ description: Select only the examples which shows your error!
options:
- label: SimpleReceiver
- label: ReceiveDemo
- label: SendRawDemo
- label: ReceiverTimingAnalysis
+ - label: ReceiveDump
- label: TinyReceiver
- label: TinySender
- label: ReceiveAndSend
- label: SimpleSender
- label: SendDemo
- - label: SendLGAirConditionerDemo
- label: UnitTest
- label: Other - please specify below
@@ -162,7 +144,7 @@ body:
1.
2.
3.
- 4. See error
+ 4.
validations:
required: true
@@ -177,9 +159,9 @@ body:
- type: textarea
id: bug-logs
attributes:
- label: The serial output which indicates the error happened.
+ label: The output which indicates the error happened.
description: |
- Please copy and paste any relevant serial output. This will be automatically formatted into code, so no need for backticks.
+ Please copy and paste any relevant output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false
@@ -212,9 +194,7 @@ body:
options:
- label: I have **read** the README.md file thoroughly
required: true
- - label: I have searched existing issues to see if there is anything I have missed.
- required: true
- - label: I have browsed the examples for one, that matches my use case.
+ - label: I have browsed the examples for one that matches my use case.
required: true
- label: The title of the issue is helpful and relevant.
required: true
@@ -222,6 +202,6 @@ body:
- type: markdown
attributes:
value: |
- ** We will start to close or delete issues that do not follow these guidelines
- as it doesn't help the contributors who spend time trying to solve issues if the community ignores guidelines!**
+ We will start to close or delete issues that do not follow these guidelines
+ as it doesn't help the contributors who spend time trying to solve issues if the community ignores guidelines!
diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml
index c6dbb9b0f..eacec58e1 100644
--- a/.github/workflows/LibraryBuild.yml
+++ b/.github/workflows/LibraryBuild.yml
@@ -47,29 +47,32 @@ jobs:
#############################################################################################################
arduino-boards-fqbn:
- arduino:avr:uno
- - arduino:avr:uno|DEBUG
+ - arduino:avr:uno|DEBUG_TRACE
- arduino:avr:uno|USE_NO_SEND_PWM
- arduino:avr:uno|SEND_PWM_BY_TIMER
- arduino:avr:uno|USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
+ - arduino:avr:uno|USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
- arduino:avr:mega:cpu=atmega2560
- arduino:avr:leonardo
- arduino:megaavr:nona4809:mode=off
- arduino:samd:arduino_zero_native
- arduino:renesas_uno:unor4wifi
- adafruit:samd:adafruit_metro_m4:cache=on,speed=120,opt=small,maxqspi=50,usbstack=arduino,debug=off
+ - adafruit:samd:adafruit_itsybitsy_m4
- 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
+ - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal
+ - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
- esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
- esp32:esp32:featheresp32:FlashFreq=80
- esp32:esp32:esp32c3
+ - esp32:esp32:lolin_s2_mini
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
- STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
- stm32duino:STM32F1:genericSTM32F103C
@@ -82,26 +85,30 @@ 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
+ ReceiveDemo: -DUSE_STRICT_DECODER -DDEBUG -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
+ SimpleSender: -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=1200 -DIR_SEND_PIN=3
- - arduino-boards-fqbn: arduino:avr:uno|DEBUG
+ - arduino-boards-fqbn: arduino:avr:uno|DEBUG_TRACE
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3
- TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER
- All: -DEBUG
+ ReceiveDemo: -DUSE_THRESHOLD_DECODER -DEBUG -DTRACE
+ IRremoteExtensionTest: -DIR_SEND_PIN=3 -DEBUG -DTRACE
+ TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER -DEBUG -DTRACE
+ All: -DEBUG -DTRACE
- arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3
+ SimpleSender: -DUSE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM
+ IRremoteExtensionTest: -DIR_SEND_PIN=3
TinyReceiver: -DUSE_FAST_PROTOCOL
TinySender: -DUSE_FAST_PROTOCOL
All: -DUSE_NO_SEND_PWM
- arduino-boards-fqbn: arduino:avr:uno|SEND_PWM_BY_TIMER
- sketches-exclude: UnitTest
+ sketches-exclude: UnitTest,MultipleSendPins
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 -DSEND_PWM_BY_TIMER
+ SimpleSender: -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
+ IRremoteExtensionTest: -DIR_SEND_PIN=3
ReceiveDemo: -DDECODE_ONKYO
TinyReceiver: -DUSE_ONKYO_PROTOCOL
TinySender: -DUSE_ONKYO_PROTOCOL
@@ -109,53 +116,57 @@ jobs:
- arduino-boards-fqbn: arduino:avr:uno|USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
+ IRremoteExtensionTest: -DIR_SEND_PIN=3 -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
SimpleSender: -DSEND_PWM_BY_TIMER
TinyReceiver: -DENABLE_NEC2_REPEATS
TinySender: -DENABLE_NEC2_REPEATS
All: -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN
+ - arduino-boards-fqbn: arduino:avr:uno|USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
+ build-properties: # the flags were put in compiler.cpp.extra_flags
+ IRremoteExtensionTest: -DIR_SEND_PIN=3 -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
+ SimpleSender: -DSEND_PWM_BY_TIMER
+ TinyReceiver: -DENABLE_NEC2_REPEATS
+ TinySender: -DENABLE_NEC2_REPEATS
+ All: -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
+
- arduino-boards-fqbn: arduino:avr:mega:cpu=atmega2560
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
+ IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=1500
SimpleSender: -DSEND_PWM_BY_TIMER
TinyReceiver: -DDISABLE_PARITY_CHECKS
TinySender: -DDISABLE_PARITY_CHECKS
- arduino-boards-fqbn: arduino:avr:leonardo
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
TinyReceiver: -DNO_LED_FEEDBACK_CODE
TinySender: -DNO_LED_FEEDBACK_CODE
-# sketches-exclude: ReceiveAndSend # Not enough RAM for default RAW_BUFFER_LENGTH
+ sketches-exclude: UnitTest # Sketch uses 28764 bytes (100%) of program storage space. Maximum is 28672 bytes
- arduino-boards-fqbn: arduino:megaavr:nona4809:mode=off
sketches-exclude: TinyReceiver,IRDispatcherDemo
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
SimpleSender: -DSEND_PWM_BY_TIMER
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
sketches-exclude: TinyReceiver,IRDispatcherDemo
- build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
- arduino-boards-fqbn: arduino:renesas_uno:unor4wifi
sketches-exclude: TinyReceiver,IRDispatcherDemo
- build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
- arduino-boards-fqbn: adafruit:samd:adafruit_metro_m4:cache=on,speed=120,opt=small,maxqspi=50,usbstack=arduino,debug=off
platform-url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
sketches-exclude: TinyReceiver,IRDispatcherDemo
- build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
+
+ - arduino-boards-fqbn: adafruit:samd:adafruit_itsybitsy_m4
+ platform-url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
+ sketches-exclude: TinyReceiver,IRDispatcherDemo
+
- arduino-boards-fqbn: arduino:mbed:nano33ble
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
SimpleSender: -DSEND_PWM_BY_TIMER
#
@@ -163,7 +174,6 @@ jobs:
#
- arduino-boards-fqbn: arduino:mbed_rp2040:pico
build-properties: # the flags were put in compiler.cpp.extra_flags
- IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750
SimpleSender: -DSEND_PWM_BY_TIMER
- arduino-boards-fqbn: rp2040:rp2040:arduino_nano_connect
@@ -171,50 +181,47 @@ jobs:
build-properties: # the flags were put in compiler.cpp.extra_flags
IRremoteExtensionTest: -DSEND_PWM_BY_TIMER
SimpleSender: -DSEND_PWM_BY_TIMER
+ SendDemo: -DSEND_PWM_BY_TIMER -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN
All: -DRAW_BUFFER_LENGTH=750
#
# megaTinyCore
#
-# https://github.com/SpenceKonde/megaTinyCore/issues/935
-# - arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal
-# arduino-platform: megaTinyCore:megaavr
-# platform-url: http://drazzy.com/package_drazzy.com_index.json
-# sketches-exclude: AllProtocolsOnLCD
-# build-properties: # the flags were put in compiler.cpp.extra_flags
-# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360
-
-# https://github.com/SpenceKonde/megaTinyCore/issues/935
-# - arduino-boards-fqbn: megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
-# arduino-platform: megaTinyCore:megaavr
-# platform-url: http://drazzy.com/package_drazzy.com_index.json
-# sketches-exclude: AllProtocolsOnLCD
-# build-properties: # the flags were put in compiler.cpp.extra_flags
-# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360
+ - arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal
+ arduino-platform: megaTinyCore:megaavr
+ platform-url: http://drazzy.com/package_drazzy.com_index.json
+ sketches-exclude: AllProtocolsOnLCD,UnitTest # UnitTest region `text' overflowed by 997 bytes
+
+ - arduino-boards-fqbn: megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
+ arduino-platform: megaTinyCore:megaavr
+ platform-url: http://drazzy.com/package_drazzy.com_index.json
+ sketches-exclude: AllProtocolsOnLCD
#
# 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: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: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,SimpleReceiverForHashCodes.ino
+ build-properties: # the flags were put in compiler.cpp.extra_flags
+ SimpleSender: -DSEND_PWM_BY_TIMER
+ SimpleReceiver: -DDECODE_NEC
+
+ - 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,SimpleReceiverForHashCodes.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,SimpleReceiverForHashCodes.ino
+ build-properties: # the flags were put in compiler.cpp.extra_flags
+ SimpleSender: -DSEND_PWM_BY_TIMER
+ SimpleReceiver: -DDECODE_NEC
#
# MegaCore
@@ -237,19 +244,21 @@ 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 as 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: -Wno-error=maybe-uninitialized
- All: -DRAW_BUFFER_LENGTH=750 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024
+ All: -DRAW_BUFFER_LENGTH=1500
- 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 as 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: -Wno-error=maybe-uninitialized
- All: -DRAW_BUFFER_LENGTH=750 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024
+ All: -DRAW_BUFFER_LENGTH=1500
+
+ - arduino-boards-fqbn: esp32:esp32:lolin_s2_mini
+ platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
+ 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!
+ All: -DRAW_BUFFER_LENGTH=1500
#
# STM
@@ -280,6 +289,7 @@ jobs:
platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here
build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled!
All: -DRAW_BUFFER_LENGTH=750
+ sketches-exclude: UnitTest # Sketch uses 28762 bytes (100%) of program storage space. Maximum is 28672 bytes.
- arduino-boards-fqbn: sandeepmistry:nRF5:BBCmicrobit
platform-url: https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json
@@ -289,7 +299,7 @@ jobs:
- arduino-boards-fqbn: Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off,sercom4=include
platform-url: https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
- sketches-exclude: AllProtocolsOnLCD,UnitTest,ReceiveAndSendDistanceWidth # No print(uint64_t,.) available
+ sketches-exclude: AllProtocolsOnLCD,UnitTest,ReceiveAndSendDistanceWidth,ReceiveDemo,SimpleReceiverForHashCodes # No print(uint64_t,.) available
build-properties: # the flags were put in compiler.cpp.extra_flags
All: -DRAW_BUFFER_LENGTH=750
@@ -303,10 +313,12 @@ jobs:
uses: ArminJo/arduino-test-compile@master
with:
arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }}
- arduino-platform: ${{ matrix.arduino-platform }}
+ arduino-platform: ${{ matrix.arduino-platform }} # for MegaCore
platform-url: ${{ matrix.platform-url }}
required-libraries: ${{ matrix.required-libraries }}
- sketch-names: ${{ matrix.sketch-names }}
+ sketch-names: ${{ matrix.sketch-names }} # Comma separated list of sketch names (without path, but with extension) or patterns to use in build
sketches-exclude: ${{ matrix.sketches-exclude }}
build-properties: ${{ toJson(matrix.build-properties) }}
- cli-version: 0.33.0 # to avoid errors for ATTinyCore
+# cli-version: 0.33.0 # to avoid errors for ATTinyCore
+# debug-install: true
+# debug-compile: true
\ No newline at end of file
diff --git a/.github/workflows/PlatformIoPublish.yml b/.github/workflows/PlatformIoPublish.yml
index cc9b32a1a..d8727408c 100644
--- a/.github/workflows/PlatformIoPublish.yml
+++ b/.github/workflows/PlatformIoPublish.yml
@@ -36,8 +36,7 @@ jobs:
env:
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_TOKEN }}
run: |
- pio package publish --owner arminjo --non-interactive
+ pio package publish --owner Arduino-IRremote --non-interactive
# run: |
# pio package pack
-# pio package publish --owner arminjo --non-interactive
-
\ No newline at end of file
+# pio package publish --owner Arduino-IRremote --non-interactive
diff --git a/Contributing.md b/Contributing.md
index 4424f809c..7483472d1 100644
--- a/Contributing.md
+++ b/Contributing.md
@@ -18,7 +18,7 @@ Refrain from using overly long or capitalized titles as they are usually annoyin
We use the original [C Style by Kerninghan / Ritchie](https://en.wikipedia.org/wiki/Indentation_style#K&R_style) in [variant: 1TBS (OTBS)](https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)).
In short: 4 spaces indentation, no tabs, opening braces on the same line, braces are mandatory on all if/while/do, no hard line length limit.
To beautify your code, you may use the online formatter [here](https://www.freecodeformat.com/c-format.php).
-#### Cover **all** occurences of the problem / addition you address with your PR
+#### Cover **all** occurrences of the problem / addition you address with your PR
Do not forget the documentation like it is done for existing code. Code changes without proper documentation will be rejected!
## Adding new protocols
diff --git a/Contributors.md b/Contributors.md
index 349ccec14..0d6ccd937 100644
--- a/Contributors.md
+++ b/Contributors.md
@@ -31,5 +31,9 @@ These are the active contributors of this project that you may contact if there
- [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.
+- [akellai](https://github.com/akellai) Added ESP 3.0 support.
+- [Hayden McAfee](https://github.com/haydenmc) Help with UnoR4 support.
+- [Yonghwan SO](https://github.com/sio4) Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306.
+- [A.R.Jung](https://github.com/arjung467) Marantz-RC5 extension support #1314.
Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed.
diff --git a/Doxyfile b/Doxyfile
index a879240e6..9e4c94a05 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -2339,7 +2339,7 @@ INCLUDED_BY_GRAPH = YES
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-CALL_GRAPH = NO
+CALL_GRAPH = YES
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
@@ -2351,7 +2351,7 @@ CALL_GRAPH = NO
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
-CALLER_GRAPH = NO
+CALLER_GRAPH = YES
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
diff --git a/README.md b/README.md
index 0ee428a6a..68c6c7681 100644
--- a/README.md
+++ b/README.md
@@ -32,25 +32,35 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
# 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)
+- [Common problem with IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-problem-with-irremote)
+- [Using the new library version for old examples](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-library-version-for-old-examples)
+ * [New features of version 4.5](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-of-version-45)
+ * [New features of version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-of-version-4x)
+ * [New features of version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-of-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)
+ * [Errors when using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#errors-when-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)
+- [Tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tutorials)
- [3 ways to specify an IR code](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#3-ways-to-specify-an-ir-code)
- [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts)
- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes)
* [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure)
* [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)
* [RAM usage of different protocolsl](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ram-usage-of-different-protocols)
+ * [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols)
+ * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer)
+ * [Other libraries, which may cover these protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#other-libraries-which-may-cover-these-protocols)
+ * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance)
+ * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown)
+ * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote)
- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes)
+ * [Sending UNKNOWN protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-unknown-protocol)
* [Sending IRDB IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-irdb-ir-codes)
* [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin)
+ * [Polarity of send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#polarity-of-send-pin)
+ [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)
@@ -59,17 +69,14 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
* [Receiving sets overflow flag](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-sets-overflow-flag)
* [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc)
* [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library)
- * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver)
+ * [Multiple IR receivers](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receivers)
+ * [Multiple IR sender instances](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-sender-instances)
* [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)
+- [IR control of a robot car](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ir-control-of-a-robot-car)
- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#issues-and-discussions)
- [Compile options / macros for 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)
@@ -93,13 +100,13 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
# Supported IR Protocols
` NEC / Onkyo / Apple ` ` Denon / Sharp ` ` Panasonic / Kaseikyo `
-` JVC ` ` LG ` ` RC5 ` ` RC6 ` ` Samsung ` ` Sony `
+` JVC ` ` LG ` ` RC5 ` ` RC6 ` ` Samsung ` ` Sony ` ` Marantz `
` Universal Pulse Distance ` ` Universal Pulse Width ` ` Universal Pulse Distance Width`
` Hash ` ` Pronto `
-` BoseWave ` ` Bang & Olufsen ` ` Lego ` ` FAST ` ` Whynter ` ` MagiQuest `
+` BoseWave ` ` Bang & Olufsen ` ` Lego ` ` FAST ` ` Whynter ` ` MagiQuest ` ` Velux `
Protocols can be switched off and on by defining macros before the line `#include ` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33):
@@ -110,13 +117,25 @@ Protocols can be switched off and on by defining macros before the line `#includ
```
-# Features
-- Lots of tutorials and examples.
-- Actively maintained.
-- Allows receiving and sending of **raw timing data**.
-
-## New features with version 4.x
-- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead.
+# Common problem with IRremote
+Or *"I build a gadged with 2 motors controlled by IR and the [IR stops after the first motor command](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor)"*.
+This is due to the fact, that the motor control by AnalogWrite() uses the same timer as IR receiving.
+See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) for the list of timers and pins.
+
+# Using the new library version for old examples
+This library has been refactored, breaking backward compatibility with the old version, on which many examples on the Internet are based.
+
+## New features of version 4.5
+- Support for **multiple receiver instances**.
+`irparams_struct irparams` is now member of `IRrecv`. Thus `rawDataPtr` (pointer to irparams) was removed from `IrReceiver.decodedIRData`.
+Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.rawbuf`, the same holds for `IrReceiver.irparams.rawlen`.
+- LED feedback is always enabled for sending. It can only be disabled by using `#define NO_LED_SEND_FEEDBACK_CODE` or `#define NO_LED_FEEDBACK_CODE`.
+- The second parameter of the function `IrSender.begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback)` has changed to `uint_fast8_t aFeedbackLEDPin`. Therefore this function call no longer works as expected because it uses the old boolean value of e.g. `ENABLE_LED_FEEDBACK` which evaluates to true or 1 as pin number of the LED feedback pin number.
+- New experimental Velux send function.
+- Send function for Marantz version of the RC5x protocol. This protocol has an additional 6 bit command extension and adds a short pause after the address is sent to identify this variant of the protocol.
+
+## New features of version 4.x
+- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `#define NO_LED_SEND_FEEDBACK_CODE` instead.
- New universal **Pulse Distance / Pulse Width / Pulse Distance 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.
@@ -125,18 +144,18 @@ Protocols can be switched off and on by defining macros before the line `#includ
- New FAST protocol.
- Automatic printout of the **corresponding send function** with `printIRSendUsage()`.
-#### Converting your 3.x program to the 4.x version
+### 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
+## New features of version 3.x
- **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**.
NEC, Panasonic, Sony, Samsung and JVC decode & send LSB first.
- Supports **Universal Distance protocol**, which covers a lot of previous unknown protocols.
-- Compatible with **tone()** library. See the [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169) example.
+- Compatible with **tone()** library. See the [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298) example.
- Simultaneous sending and receiving. See the [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino#L167-L170) example.
- Supports **more platforms**.
- Allows for the generation of non PWM signal to just **simulate an active low receiver signal** for direct connect to existent receiving devices without using IR.
@@ -148,25 +167,26 @@ Protocols can be switched off and on by defining macros before the line `#includ
-# Converting your 2.x program to the 4.x version
+## Converting your 2.x program to the 4.x version
Starting with the 3.1 version, **the generation of PWM for sending is done by software**, thus saving the hardware timer and **enabling arbitrary output pins for sending**.
-If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, if you get false error messages regarding begin() during compilation.
+If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h,
+if you get false error messages regarding begin() during compilation.
- **IRreceiver** and **IRsender** object have been added and can be used without defining them, like the well known Arduino **Serial** object.
-- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program, and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`.
-- Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar.
+- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`.
- Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106)
or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin();` in setup().
-If IR_SEND_PIN is not defined (before the line `#include `) you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);`
+If IR_SEND_PIN is not defined (before the line `#include `) you must use e.g. `IrSender.begin(3);`
- 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`.
+- Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.irparams.rawbuf` and `IrReceiver.decodedIRData.rawlen`.
-- 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.
-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).
+- 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 therefore was assumed to be never used.
+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) or use the new functions `bitreverseOneByte()` or `bitreverse32Bit()` for reversing.
### Example
#### Old 2.x program:
@@ -181,6 +201,7 @@ decode_results results;
void setup()
{
...
+ Serial.begin(115200); // Establish serial communication
irrecv.enableIRIn(); // Start the receiver
}
@@ -203,6 +224,7 @@ void loop() {
void setup()
{
...
+ Serial.begin(115200); // // Establish serial communication
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
}
@@ -218,32 +240,52 @@ void loop() {
}
```
+#### Sample output
+For more, see the [UnitTest log](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/UnitTest/UnitTest.log).
+
+```
+Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
+Send with: IrSender.sendNEC(0xF1, 0x76, );
+
+Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, );
+```
+
## How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes
For the new decoders for **NEC, Panasonic, Sony, Samsung and JVC**, the result `IrReceiver.decodedIRData.decodedRawData` is now **LSB-first**, as the definition of these protocols suggests!
-To convert one into the other, you must reverse the byte/nibble positions and then reverse all bit positions of each byte/nibble or write it as one binary string and reverse/mirror it.
-Example:
-`0xCB 34 01 02`
+To convert one into the other, you must reverse the nibble (4 bit / Hex numbers) positions and then reverse all bit positions of each nibble or write it as one binary string and reverse/mirror it.
+This can be done by using the new functions `bitreverseOneByte()` or `bitreverse32Bit()`.
+
+### Nibble reverse
+`0xCB 34 01 02` MSB value
`0x20 10 43 BC` after nibble reverse
-`0x40 80 2C D3` after bit reverse of each nibble
-### Nibble reverse map:
+`0x40 80 2C D3` LSB value after bit reverse of each nibble
+
+### Nibble reverse map
```
0->0 1->8 2->4 3->C
4->2 5->A 6->6 7->E
8->1 9->9 A->5 B->D
C->3 D->B E->7 F->F
```
+
+### Binary string reverse
+If you **read the first binary sequence backwards** (right to left), you get the second sequence.
`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
-`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.
-If you **read the first binary sequence backwards** (right to left), you get the second sequence.
-You may use `bitreverseOneByte()` or `bitreverse32Bit()` for this.
+`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`.
+### Online tool which reverses every byte, but not the order of the bytes
+Use this [tool provided by analysir](https://www.analysir.com/hex2nec.php).
+
+### Send MSB directly
Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
-# Errors 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).
+## Errors when using the 4.x versions for old tutorials
+If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`,
+just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
Most likely your code will run and you will not miss the new features.
@@ -252,7 +294,7 @@ 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.
It may be sufficient and deals flawlessly with 32 bit IR codes.
-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.
+If this doesn't work for you, you can be sure that 4.x is trying to be compatible with earlier versions, so your old examples should work just fine.
### Drawbacks of using 2.x
- Only the following decoders are available:
@@ -267,9 +309,10 @@ If this doesn't fit your case, be assured that 4.x is at least trying to be back
**Every \*.cpp file is compiled separately** by a call of the compiler exclusively for this cpp file. These calls are managed by the IDE / make system.
In the Arduino IDE the calls are executed when you click on *Verify* or *Upload*.
-And now our problem with Arduino is:
+And now **our problem with Arduino** is:
**How to set [compile options](#compile-options--macros-for-this-library) for all *.cpp files, especially for libraries used?**
-IDE's like [Sloeber](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-sloeber-ide) or [PlatformIO](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project.
+IDE's like [Sloeber](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) or
+[PlatformIO](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project.
They add these options at each compiler call e.g. `-DTRACE`.
But Arduino lacks this feature.
@@ -277,10 +320,10 @@ So the **workaround** is not to compile all sources separately, but to concatena
This is done by e.g. `#include "IRremote.hpp"`.
But why not `#include "IRremote.cpp"`?
-Try it and you will see tons of errors, because each function of the *.cpp file is now compiled twice,
-first by compiling the huge file and second by compiling the *.cpp file separately, like described above.
-So using the extension *cpp* is not longer possible, and one solution is to use *hpp* as extension, to show that it is an included *.cpp file.
-Every other extension e.g. *cinclude* would do, but *hpp* seems to be common sense.
+If you try it, you will see lots of errors, because each function of the *.cpp file is now compiled twice:
+first when the huge file is compiled, and second when the .cpp file is compiled separately, as described above.
+Therefore, using the **.cpp** extension is no longer possible. One solution is to use the **.hpp** extension to indicate that it is an included .cpp file.
+Any other extension would work, e.g. *cinclude*, but *hpp* seems to be common sense.
# Using the new *.hpp files
In order to support [compile options](#compile-options--macros-for-this-library) more easily,
@@ -301,6 +344,10 @@ The following macros will definitely be overridden with default values otherwise
+# Tutorials
+- A very elaborated introduction to IR remotes and IRremote library from [DroneBot Workshop ](https://dronebotworkshop.com/ir-remotes/).
+
+
# 3 ways to specify an IR code
There are 3 different ways of specifying a particular IR code.
@@ -348,6 +395,9 @@ Often the address is also constant, which further reduces memory requirements.
# IRReceiver pinouts

+[Adafruit IR Sensor tutorial](https://learn.adafruit.com/ir-sensor)
+
+
# Receiving IR codes
In your program you check for a **completely received IR frame** with:
`if (IrReceiver.decode()) {}`
@@ -361,15 +411,19 @@ struct IRData {
uint16_t address; // Decoded address
uint16_t command; // Decoded command
uint16_t extra; // Used for Kaseikyo unknown vendor ID. Ticks used for decoding Distance protocol.
+ IRRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions.
+#if defined(DECODE_DISTANCE_WIDTH)
+ DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes
+ IRRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; // 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions.
+#endif
uint16_t numberOfBits; // Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; // IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions
- IRRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions.
- uint32_t decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; // 32 bit decoded raw data, to be used for send function.
- irparams_struct *rawDataPtr; // Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
+ IRRawlenType rawlen; // Counter of entries in rawbuf of last received frame.
+ uint16_t initialGapTicks; // Contains the initial gap of the last received frame.
};
```
#### Flags
-This is the [list of flags](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L88) contained in the flags field.
+This is the [list of flags](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L143) contained in the flags field.
Check it with e.g. `if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)`.
| Flag name | Description |
@@ -398,7 +452,8 @@ IrReceiver.printIRResultShort(&Serial);
```c++
IrReceiver.printIRResultRawFormatted(&Serial, true);`
```
-The raw data depends on the internal state of the Arduino timer in relation to the received signal and might therefore be slightly different each time. (resolution problem). The decoded values are the interpreted ones which are tolerant to such slight differences!
+The raw data depends on the internal state of the Arduino timer in relation to the received signal and might therefore be slightly different each time. (resolution problem).
+The decoded values are the interpreted ones which are tolerant to such slight differences!
#### Print how to send the received data:
```c++
@@ -432,16 +487,10 @@ But be careful, the NEC2 protocol can only be detected by the NEC library decode
### 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.
-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.
-
## RAM usage of different protocols
The `RAW_BUFFER_LENGTH` determines the length of the **byte buffer** where the received IR timing data is stored before decoding.
**100** is sufficient for standard protocols **up to 48 bits**, with 1 bit consisting of one mark and space.
-We always require additional 4 btes, 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit.
+We always require additional 4 bytes, 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit.
- **48** bit protocols are PANASONIC, KASEIKYO, SAMSUNG48, RC6.
- **32** bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28) require a **buffer length of 68**.
- **16** bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) require a **buffer length of 36**.
@@ -451,8 +500,71 @@ We always require additional 4 btes, 1 byte for initial gap, 2 bytes for header
If the record gap determined by `RECORD_GAP_MICROS` is changed from the default 8 ms to more than 20 ms, the buffer is no longer a byte but a uint16_t buffer, requiring twice as much RAM.
+## Handling unknown Protocols
+### Disclaimer
+**This library was designed to fit inside MCUs with relatively low levels of resources and was intended to work as a library together with other applications which also require some resources of the MCU to operate.**
+
+Use the **ReceiveDemo example** to print out all informations about your IR protocol.
+The **ReceiveDump example** gives you more information but has bad repeat detection due to the time required for printing the information.
+
+### Other libraries, which may cover these protocols
+#### IRMP
+If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP), which especially supports manchester protocols much better.
+
+#### IRremoteESP8266
+For **air conditioners** , you may try the [IRremoteESP8266 library](https://github.com/crankyoldgit/IRremoteESP8266), which supports an impressive set of protocols and a lot of air conditioners and works also on ESP32.
+
+#### rawirdecode and HeatpumpIR
+[Raw-IR-decoder-for-Arduino](https://github.com/ToniA/Raw-IR-decoder-for-Arduino) is not a library, but an arduino example sketch, which provides many methods of decoding especially **air conditioner** protocols. Sending of these protocols can be done by the Arduino library [HeatpumpIR](https://github.com/ToniA/arduino-heatpumpir).
+
+
+### Protocol=PULSE_DISTANCE
+If you get something like this:
+```
+PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC
+```
+then you have a code consisting of **56 bits**, which is probably from an air conditioner remote.
+You can send it with `sendPulseDistanceWidth()`.
+```c++
+uint32_t tRawData[] = { 0xB02002, 0xA010 };
+IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0);
+```
+You can send it with calling `sendPulseDistanceWidthData()` twice, once for the first 32 bit and next for the remaining 24 bits.
+The `PULSE_DISTANCE` / `PULSE_WIDTH` decoder just decodes a timing stream to a bitstream stored as hex values.
+These decoders can not put any semantics like address, command or checksum on this bitstream.
+But the bitstream is way more readable, than a timing stream. This bitstream is read **LSB first by default**.
+If LSB does not suit for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L78).
+
+**If RAM is not more than 2k, the decoder only accepts mark or space durations up to 2500 microseconds to save RAM space, otherwise it accepts durations up to 10 ms.**
+
+### Protocol=UNKNOWN
+If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as output of e.g. the ReceiveDemo example, you either have a problem with decoding a protocol, or an unsupported protocol.
+
+- If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak.
+- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby.
+- If you see timings like `+ 500,- 550 + 450,- 550 + 450,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding.
+- If you see `Protocol=UNKNOWN Hash=0x0 1 bits received` it may be that the space after the initial mark is longer than [`RECORD_GAP_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L124).
+ This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your .ino file.
+- To see more info supporting you to find the reason for your UNKNOWN protocol, you must enable the line `//#define DEBUG` in IRremoteInt.h.
+
+### How to deal with protocols not supported by IRremote
+If you do not know which protocol your IR transmitter uses, you have several choices.
+- Just use the hash value to decide which command was received. See the [SimpleReceiverForHashCodes example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino).
+- Use the [IRreceiveDemo example](examples/ReceiveDemo) or [IRreceiveDump example](examples/ReceiveDump) to dump out the IR timing.
+ You can then reproduce/send this timing with the [SendRawDemo example](examples/SendRawDemo).
+- The [IRMP AllProtocol example](https://github.com/IRMP-org/IRMP#allprotocol-example) prints the protocol and data for one of the **[40 supported protocols](https://github.com/IRMP-org/IRMP?tab=readme-ov-file#list-of-protocols)**.
+ The same library can be used to send this codes.
+- If you have a bigger Arduino board at hand (> 100 kByte program memory) you can try the
+ [IRremoteDecode example](https://github.com/bengtmartensson/Arduino-DecodeIR/blob/master/examples/IRremoteDecode/IRremoteDecode.ino) of the Arduino library [DecodeIR](https://github.com/bengtmartensson/Arduino-DecodeIR).
+- Use [IrScrutinizer](http://www.harctoolbox.org/IrScrutinizer.html).
+ It can automatically generate a send sketch for your protocol by exporting as "Arduino Raw". It supports IRremote,
+ the old [IRLib](https://github.com/cyborg5/IRLib) and [Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino).
+
+
+
# Sending IR codes
-If you have a device at hand which can generate the IR codes you want to work with (aka IR remote), **it is recommended** to receive the codes with the [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino), which will tell you on the serial output how to send them.
+If you have a device at hand which can generate the IR codes you want to work with (aka IR remote),
+**it is recommended** to receive the codes with the [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino), which will tell you on the serial output how to send them.
```
Protocol=LG Address=0x2 Command=0x3434 Raw-Data=0x23434E 28 bits MSB first
@@ -461,28 +573,49 @@ Send with: IrSender.sendLG(0x2, 0x3434, );
You will discover that **the address is a constant** and the commands sometimes are sensibly grouped.
If you are uncertain about the numbers of repeats to use for sending, **3** is a good starting point. If this works, you can check lower values afterwards.
-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.
+If you have enabled `DECODE_DISTANCE_WIDTH`, the code printed by `printIRSendUsage()` **differs between 8 and 32 bit platforms**,
+so it is best to run the receiving program on the same platform as the sending program.
**All sending functions support the sending of repeats** if sensible.
Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms from start to start for NEC.
Keep in mind, that **there is no delay after the last sent mark**.
If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding.
-Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
+Bear in mind, that **some devices only accept commands if they are repeated one or two times**.
+
+Sending **old MSB codes without conversion** can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`
+or by [converting them manually to LSB](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes).
+
+## Sending UNKNOWN protocol
+If the protocol is unknown by IRremote, which often is the case for airconditioner codes,
+you can store the timing sequence in an array and send it with IrSender.sendRaw() or IrSender.sendRaw_P()
+like done in [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendDemo/SendDemo.ino#L180).
+Do not forget to send repeats.
## Sending IRDB IR codes
The codes found in the [Flipper-IRDB database](https://github.com/Lucaslhm/Flipper-IRDB) are quite straightforward to convert, because the also use the address / command scheme.
-Protocol matching is NECext -> NECext (or Onkyo), Samsung32 -> Samsung, SIRC20 -> Sony with 20 bits etc.
+Protocol matching is NECext -> Onkyo, Samsung32 -> Samsung, SIRC20 -> Sony with 20 bits etc.
The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**.
-Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
-An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols). "D" and "S" denotes device and subdevice and "F" denotes the function.
+Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function*
+is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters
+like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
+An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols).
+"D" and "S" denotes device and subdevice and "F" denotes the function.
## Send pin
-Any pin can be chosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
+Any pin can be chosen as send pin as long as `IR_SEND_PIN` is **not** defined.
+This is because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
On **ESP32** ledc channel 0 is used for generating the IR PWM.
-If `IR_SEND_PIN` is specified (as c macro), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro.
-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).
+If `IR_SEND_PIN` is specified (as C macro), it reduces program size and improves send timing for AVR.
+If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro e.g. with `#undef IR_SEND_PIN`.
+Then you can change send pin at any time before sending an IR frame.
+See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library).
+
+## Polarity of send pin
+By default the polarity is HIGH for active and LOW for inactive or pause.
+This corresponds to the connection schema: Pin -> Resistor-> IR-LED -> Ground.
+If you want to use the connection schema: VCC -> IR-LED -> Resistor -> Pin, you must specify `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN`.
### List of public IR code databases
http://www.harctoolbox.org/IR-resources.html
@@ -501,9 +634,17 @@ http://www.harctoolbox.org/IR-resources.html
# Tiny NEC receiver and sender
-For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
+For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
which has very **small code size of 500 bytes and does NOT require any timer**.
+## Principle of operation
+Instead of sampling the input every 50 µs as IRremote does, TinyReceiver receiver uses a **pin change interrupt** for on-the-fly decoding which limits the choice of protocols.
+On each level change, the level and the time since the last change are used to incrementally decode the protocol.
+With this operating principle, we **cannot wait for a timeout** and then decode the protocol as IRremote does.
+Instead, we need to know which is the last bit (level change) of a protocol to do the final decoding
+and the call of the optional **user provided callback function** `handleReceivedTinyIRData()`.
+This means, **we need to know the number of bits in a protocol** and therefore the protocol (family).
+
Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`.
@@ -518,10 +659,10 @@ void setup() {
}
void loop() {
- if (TinyIRReceiverData.justWritten) {
- TinyIRReceiverData.justWritten = false;
+ if (TinyReceiverDecode()) {
printTinyReceiverResultMinimal(&Serial);
}
+ // No resume() required :-)
}
```
@@ -584,17 +725,17 @@ On some boards where a software timer is available, the software timer is used.<
Be aware that the hardware timer used for receiving should not be used for `analogWrite()`.
Especially **motor** control often uses the `analogWrite()` function and will therefore stop the receiving if used on the pins indicated [here](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
On the Uno and other AVR boards the receiver timer ist the same as the tone timer. Thus receiving will stop after a `tone()` command.
-See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/b962db8f4e47408df01474a57f313f5a6bbe39a1/examples/ReceiveDemo/ReceiveDemo.ino#L257) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`.
+See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`.
## Receiving sets overflow flag.
The flag `IRDATA_FLAGS_WAS_OVERFLOW` is set, if `RAW_BUFFER_LENGTH` is too small for all the marks and spaces of the protocol.
This can happen on long protocol frames like the ones from air conditioner.
-It also can happen, if `RECORD_GAP_MICROS` is smaller than the real gap between a frame and thr repetition frame, thus interpreting both as one consecutive frame.
+It also can happen, if `RECORD_GAP_MICROS` is smaller than the real gap between a frame and the repetition frame, thus interpreting both as one consecutive frame.
Best is to dump the timing then, to see which reason holds.
## Problems with Neopixels, FastLed etc.
IRremote will not work right when you use **Neopixels** (aka WS2811/WS2812/WS2812B) or other libraries blocking interrupts for a longer time (> 50 µs).
-Whether you use the Adafruit Neopixel lib, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs.
+Whether you use the Adafruit Neopixel library, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs.
In turn, this stops the IR interrupt handler from running when it needs to. See also this [video](https://www.youtube.com/watch?v=62-nEJtm070).
One **workaround** is to wait for the IR receiver to be idle before you send the Neopixel data with `if (IrReceiver.isIdle()) { strip.show();}`.
@@ -606,15 +747,20 @@ There are some other solutions to this on more powerful processors,
**Another library is only working/compiling** if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.
This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
-## Multiple IR receiver and sender
-**This library supports only one IR receiver and one IR sender object (IRrecv and IRsend) per CPU.**
-However since sending is a serial task, you can use `setSendPin()` to switch the pin to send, thus emulating multiple sender.
-The receiver uses a special **timer** triggered function, which reads the digital IR signal value from one pin every 50 µs.
-So **multiple IR receivers** can only be used by connecting the output pins of several IR receivers together.
+## Multiple IR receivers
+**This library now supports multiple IR receiver instances (IRrecv) per CPU** see the [MultipleReceivers example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/MultipleReceivers/MultipleReceivers.ino).
+
+There is also another way to use multiple receivers.
+You can connect the output pins of each IR receiver to one input pin.
+Then you can use the standard receiver object (IrReceiver).
The IR receiver modules internally use an NPN transistor as output device with just a 30k resistor to VCC.
This is basically an "open collector" and allows multiple output pins to be connected to one Arduino input pin.
However, keep in mind that any weak / disturbed signal from one of the receivers will also interfere with a good signal from another receiver.
+## Multiple IR sender instances
+**This library only supports one IR sender object (IRsend) per CPU.**
+However since sending is a serial task, you can use `setSendPin()` to switch the pin to send, thus emulating multiple sender.
+
## Increase strength of sent output signal
**The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.2 volt at 20 mA or 1.5 volt at 100 mA so you can supply up to 3 diodes with a 5 volt output.
To power **2 diodes** with 1.2 V and 20 mA and a 5 V supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
@@ -626,8 +772,9 @@ On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :gr
## Minimal CPU clock frequency
For receiving, the **minimal CPU clock frequency is 4 MHz**, since the 50 µs timer ISR (Interrupt Service Routine) takes around 12 µs on a 16 MHz ATmega.
-The TinyReceiver, which reqires no polling, runs with 1 MHz.
-For sending, the **default software generated PWM has problems on AVR running with 8 MHz**. The PWM frequency is around 30 instead of 38 kHz and RC6 is not reliable. You can switch to timer PWM generation by `#define SEND_PWM_BY_TIMER`.
+The TinyReceiver, which requires no polling, runs with 1 MHz.
+For sending, the **default software generated PWM has problems on AVR running with 8 MHz**. The PWM frequency is around 30 instead of 38 kHz and RC6 is not reliable.
+You can switch to timer PWM generation by `#define SEND_PWM_BY_TIMER`.
## Bang & Olufsen protocol
The Bang & Olufsen protocol decoder is not enabled by default, i.e if no protocol is enabled explicitly by #define `DECODE_`. It must always be enabled explicitly by `#define DECODE_BEO`.
@@ -635,145 +782,97 @@ This is because it has an **IR transmit frequency of 455 kHz** and therefore req
And because **generating a 455 kHz PWM signal is currently only implemented for `SEND_PWM_BY_TIMER`**, sending only works if `SEND_PWM_BY_TIMER` or `USE_NO_SEND_PWM` is defined.
For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L44).
-# Handling unknown Protocols
-## Disclaimer
-**This library was designed to fit inside MCUs with relatively low levels of resources and was intended to work as a library together with other applications which also require some resources of the MCU to operate.**
-
-For **air conditioners** [see this fork](https://github.com/crankyoldgit/IRremoteESP8266), which supports an impressive set of protocols and a lot of air conditioners.
-
-For **long signals** see the blog entry: ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino).
-
-
-## Protocol=PULSE_DISTANCE
-If you get something like this:
-```
-PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC
-```
-then you have a code consisting of **56 bits**, which is probably from an air conditioner remote.
-You can send it with `sendPulseDistanceWidth()`.
-```c++
-uint32_t tRawData[] = { 0xB02002, 0xA010 };
-IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0);
-```
-You can send it with calling `sendPulseDistanceWidthData()` twice, once for the first 32 bit and next for the remaining 24 bits.
-The `PULSE_DISTANCE` / `PULSE_WIDTH` decoder just decodes a timing stream to a bitstream stored as hex values.
-These decoders can not put any semantics like address, command or checksum on this bitstream.
-But the bitstream is way more readable, than a timing stream. This bitstream is read **LSB first by default**.
-If LSB does not suit for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L78).
-
-**If RAM is not more than 2k, the decoder only accepts mark or space durations up to 2500 microseconds to save RAM space, otherwise it accepts durations up to 10 ms.**
-
-## Protocol=UNKNOWN
-If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as output of e.g. the ReceiveDemo example, you either have a problem with decoding a protocol, or an unsupported protocol.
-
-- If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak.
-- If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby.
-- If you see timings like `+ 500,- 550 + 450,- 550 + 450,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding.
-- If you see `Protocol=UNKNOWN Hash=0x0 1 bits received` it may be that the space after the initial mark is longer than [`RECORD_GAP_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.h#L124).
- This was observed for some LG air conditioner protocols. Try again with a line e.g. `#define RECORD_GAP_MICROS 12000` before the line `#include ` in your .ino file.
-- To see more info supporting you to find the reason for your UNKNOWN protocol, you must enable the line `//#define DEBUG` in IRremoteInt.h.
-
-## How to deal with protocols not supported by IRremote
-If you do not know which protocol your IR transmitter uses, you have several choices.
-- Just use the hash value to decide which command was received. See the [SimpleReceiverForHashCodes example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino).
-- Use the [IRreceiveDump example](examples/ReceiveDump) to dump out the IR timing.
- You can then reproduce/send this timing with the [SendRawDemo example](examples/SendRawDemo).
- For **long codes** with more than 48 bits like from air conditioners, you can **change the length of the input buffer** in [IRremote.h](src/IRremoteInt.h#L36).
-- The [IRMP AllProtocol example](https://github.com/IRMP-org/IRMP#allprotocol-example) prints the protocol and data for one of the **40 supported protocols**.
- The same library can be used to send this codes.
-- If you have a bigger Arduino board at hand (> 100 kByte program memory) you can try the
- [IRremoteDecode example](https://github.com/bengtmartensson/Arduino-DecodeIR/blob/master/examples/IRremoteDecode/IRremoteDecode.ino) of the Arduino library [DecodeIR](https://github.com/bengtmartensson/Arduino-DecodeIR).
-- Use [IrScrutinizer](http://www.harctoolbox.org/IrScrutinizer.html).
- It can automatically generate a send sketch for your protocol by exporting as "Arduino Raw". It supports IRremote,
- the old [IRLib](https://github.com/cyborg5/IRLib) and [Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino).
-
-
-
# Examples for this library
The examples are available at File > Examples > Examples from Custom Libraries / IRremote.
- In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.
+**In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.**
See also [DroneBot Workshop SimpleReceiver](https://dronebotworkshop.com/ir-remotes/#SimpleReceiver_Example_Code) and [SimpleSender](https://dronebotworkshop.com/ir-remotes/#SimpleSender_Example_Code).
-#### SimpleReceiver + SimpleSender
-The **[SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** and **[SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)** examples are a good starting point.
+### [SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino) + [SimpleSender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/SimpleSender.ino)
+The **SimpleReceiver** and **SimpleSender** examples are a good starting point.
A simple example can be tested online with [WOKWI](https://wokwi.com/projects/338611596994544210).
-#### SimpleReceiverForHashCodes
-The **[SimpleReceiverForHashCodes](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** uses only the hash decoder.
+### [SimpleReceiverForHashCodes](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino)
+The **SimpleReceiverForHashCodes** uses only the hash decoder.
It converts all IR frames longer than 6 to a 32 bit hash code, thus enabling receiving of unknown protocols.
See: http://www.righto.com/2010/01/using-arbitrary-remotes-with-arduino.html
-#### TinyReceiver + TinySender
+### [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino) + [TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)
If **code size** or **timer usage** matters, look at these examples.
-The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library
+The **TinyReceiver** example uses the **TinyIRReceiver** library
which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**.
They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
-The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
+The **TinySender** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example. It has options to send using Extended NEC, ONKYO and FAST protocols.
Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible).
-#### SmallReceiver
+### [SmallReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino)
If the protocol is not NEC and code size matters, look at this [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SmallReceiver/SmallReceiver.ino).
-#### ReceiveDemo + AllProtocolsOnLCD
-[ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.
+### [ReceiveDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino) + [AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino)
+ReceiveDemo receives all protocols and **generates a beep with the Arduino tone() function** on each packet received.
Long press of one IR button (receiving of multiple repeats for one command) is detected.
-[AllProtocolsOnLCD](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino) additionally **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).
+AllProtocolsOnLCD additionally **displays the short result on a 1602 LCD**.
+The LCD can be connected parallel or serial (I2C).
By connecting debug pin to ground, you can force printing of the raw values for each frame. The pin number of the debug pin is printed during setup, because it depends on board and LCD connection type.
This example also serves as an **example how to use IRremote and tone() together**.
-#### ReceiveDump
-Receives all protocols and dumps the received signal in different flavors including Pronto format. Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN.
+#### [ReceiveDump](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDump/ReceiveDump.ino)
+Receives all protocols and dumps the received signal in different flavors including **Pronto format**.
+Since the printing takes much time, repeat signals may be skipped or interpreted as UNKNOWN.
-#### SendDemo
+#### [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendDemo/SendDemo.ino)
Sends all available protocols at least once.
-#### SendAndReceive
+#### [MultipleSendPins](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/MultipleSendPins/MultipleSendPins.ino)
+Demonstrates sending IR codes toggling between 2 **different send pins**.
+
+#### [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino)
Demonstrates **receiving while sending**.
-#### ReceiveAndSend
-Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the approriate protocol encoder. `UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`.
+#### [ReceiveAndSend](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSend/ReceiveAndSend.ino)
+Record and **play back last received IR signal** at button press. IR frames of known protocols are sent by the appropriate protocol encoder.
+`UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`.
-#### ReceiveAndSendDistanceWidth
+#### [ReceiveAndSendDistanceWidth](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino)
Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.
If RAM is not more than 2k, the decoder only accepts mark or space durations up to 2500 microseconds to save RAM space, otherwise it accepts durations up to 10 ms.
Storing data for distance width protocol requires 17 bytes.
The ReceiveAndSend example requires 16 bytes for known protocol data and 37 bytes for raw data of e.g.NEC protocol.
-#### ReceiveOneAndSendMultiple
+#### [ReceiveOneAndSendMultiple](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino)
Serves as a IR **remote macro expander**. Receives Samsung32 protocol and on receiving a specified input frame, it sends multiple Samsung32 frames with appropriate delays in between.
This serves as a **Netflix-key emulation** for my old Samsung H5273 TV.
-#### IRDispatcherDemo
+#### [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/IRDispatcherDemo.ino)
Framework for **calling different functions of your program** for different IR codes.
-#### IRrelay
+#### [ControlRelay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ControlRelay/ControlRelay.ino)
**Control a relay** (connected to an output pin) with your remote.
-#### IRremoteExtensionTest
-[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino) for a user defined class, which itself uses the IRrecv class from IRremote.
+#### [IRremoteExtensionTest](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino)
+Example for a user defined class, which itself uses the IRrecv class from IRremote.
-#### SendLGAirConditionerDemo
-[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino) for sending LG air conditioner IR codes controlled by Serial input.
+#### [SendLGAirConditionerDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino)
+Example for sending LG air conditioner IR codes controlled by Serial input.
By just using the function `bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter)` you can control the air conditioner by any other command source.
The file *acLG.h* contains the command documentation of the LG air conditioner IR protocol. Based on reverse engineering of the LG AKB73315611 remote.

IReceiverTimingAnalysis can be tested online with [WOKWI](https://wokwi.com/projects/299033930562011656)
Click on the receiver while simulation is running to specify individual IR codes.
-#### ReceiveAndSendHob2Hood
-[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/ReceiveAndSendHobToHood.ino) for receiving and sending AEG / Elektrolux Hob2Hood protocol.
+#### [ReceiveAndSendHob2Hood](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino)
+Example for receiving and sending AEG / Elektrolux Hob2Hood protocol.
-#### 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.
+#### [ReceiverTimingAnalysis](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino)
+This example analyzes the signal delivered by your IR receiver module.
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.
It also computes the `MARK_EXCESS_MICROS` value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656).
Click on the receiver while simulation is running to specify individual NEC IR codes.
-#### UnitTest
+#### [UnitTest](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/UnitTest/UnitTest.ino)
ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**.
Here you see the delay of the receiver output (blue) from the IR diode input (yellow).

@@ -785,6 +884,14 @@ Here you see the delay of the receiver output (blue) from the IR diode input (ye
- [ReceiverTimingAnalysis](https://wokwi.com/projects/299033930562011656)
- [Receiver with LCD output and switch statement](https://wokwi.com/projects/298934082074575369)
+# IR control of a robot car
+This [example](https://github.com/ArminJo/PWMMotorControl?tab=readme-ov-file#basicircontrol) of the **Arduino PWMMotorControl library** controls the basic functions of a robot car using the IRremote library.
+It controls 2 PWM motor channels, 2 motors at each channel.
+[Here](https://www.instructables.com/Arduino-4WD-Car-Assembly-and-Code-With-Optional-In/) you can find the instructable for car assembly and code.
+
+IR_RobotCar with TL1838 IR receiver plugged into expansion board.
+
+
# Issues and discussions
@@ -803,23 +910,27 @@ Modify them by enabling / disabling them, or change the values if applicable.
|-|-:|-|
| `RAW_BUFFER_LENGTH` | 200 | Buffer size of raw input uint16_t buffer. Must be even! If it is too small, overflow flag will be set. 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. A value of 200 requires 200 bytes RAM. |
| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance width protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. |
+| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. |
| `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) |
-| `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. |
+| `USE_THRESHOLD_DECODER` | disabled | If enabled, may give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses and forces value of MARK_EXCESS_MICROS to 0 to save program memory. Requires up to additional 120 bytes program memory. |
+| `USE_STRICT_DECODER` | disabled | Check for all 4 one and zero protocol timings. Only sensible for development or very exotic requirements. Requires up to 300 additional bytes of program memory. |
| `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. |
-| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. |
+| `MARK_EXCESS_MICROS` | 0 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. Is set to 20 if `DO_NOT_USE_THRESHOLD_DECODER` is enabled. |
| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. |
| `DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE` | 50 if RAM <= 2k, else 200 | A value of 200 allows to decode mark or space durations up to 10 ms. |
| `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). |
+| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the **advantage of more exact PWM generation**, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the **disadvantage of using a hardware timer**, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM generation for each pin without using a shared resource (timer). |
| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. |
-| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
+| `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverses the polarity at the send pin. Can be used to connect IR LED between VCC and the send pin. It is like open drain but with electrical active high in its logical inactive state. |
| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode 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. |
+| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. |
+| `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` | disabled | Only 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. |
+| `NO_LED_RECEIVE_FEEDBACK_CODE` | disabled | Disables the LED feedback code for receive. Saves around 100 bytes program memory for receiving and halving the receiver ISR (Interrupt Service Routine) processing time. |
+| `NO_LED_SEND_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send. Saves around 322 bytes for sending. |
| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. |
| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT` | 25 | Relative tolerance for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. |
| `DEBUG` | disabled | Enables lots of lovely debug output. |
@@ -828,15 +939,17 @@ Modify them by enabling / disabling them, or change the values if applicable.
These next macros for **TinyIRReceiver** must be defined in your program before the line `#include ` to take effect.
| Name | Default value | Description |
|-|-:|-|
-| `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. |
+| `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. Not used in IRremote. |
| `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. |
-| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. |
-| `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. |
+| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED code for send and receive. Saves 14 bytes program memory. |
+| `NO_LED_RECEIVE_FEEDBACK_CODE` | disabled | Disables the LED feedback code for receive. |
+| `NO_LED_SEND_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send. |
+| `DISABLE_PARITY_CHECKS` | disabled | Disables the address and command parity checks. Saves 48 bytes program memory. |
| `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. |
| `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. |
| `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. |
-| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. |
+| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the user provided function `void handleReceivedTinyIRData()` each time a frame or repeat is received. |
The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect.
| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. |
@@ -861,10 +974,11 @@ If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easi
# Supported Boards
**Issues and discussions with the content "Is it possible to use this library with the ATTinyXYZ? / board XYZ" without any reasonable explanations will be immediately closed without further notice.**
-For **ESP8266/ESP32**, [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)
+For **ESP8266/ESP32**, [the IRremoteESP8266 library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)
+**ATtiny CPU's are tested with the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) library**.
Digispark boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the Digispark Pro board.
-ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore).
+**ATtiny boards** are tested with **[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore) only**.
- 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`.
@@ -876,9 +990,9 @@ ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/A
- ATmega4809 (Nano every)
- ATtiny3217 (Tiny Core 32 Dev Board)
- ATtiny84, 85, 167 (Digispark + Digispark Pro)
-- SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**)
+- SAMD (Zero, MKR*, **but not DUE, the latter is SAM architecture**)
- ESP8266
-- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) **not for ESP32 core version > 3.0.0**
+- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif). New CPUs (as of January 2025) are not guaranteed to work!
- Sparkfun Pro Micro
- Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE
- BluePill with STM32
@@ -894,7 +1008,7 @@ If you can provide **examples of using a periodic timer for interrupts** for the
# Timer and pin usage
The **receiver sample interval of 50 µs is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used.
On **ESP8266** `timer1` is used for receive interrupts, which makes it incompatible to the Servo and other libraries.
-On **ESP32** `hw_timer_t` is used for receive interrupts and `ledc` channel 0 is used for generating the IR PWM.
+On **ESP32** `hw_timer_t` is used for receive interrupts.
Every pin can be used for receiving.
If software PWM is selected, which is default, every pin can also be used for sending. Sending with software PWM does not require a timer!
@@ -936,7 +1050,7 @@ The code for the timer and the **timer selection** is located in [private/IRTime
| [Teensy 4.0 - 4.1](https://www.pjrc.com/teensy/pinout.html) | **FlexPWM1.3** | **8** | 7, 25 |
| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** |
| [BluePill / STM32F103C8T6](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill) | **TIM4** | % | **PB6 & PB7 & PB8 & PB9** |
-| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin |
+| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://www.raspberrypi.com/documentation/pico-sdk/high_level.html#group_alarm_1ga40b4a03bf9e967d4e7170d20c5c9fb15) | All pins | No pin |
| [RP2040 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin |
### No timer required for sending
@@ -953,8 +1067,11 @@ Since the Arduino `micros()` function has a resolution of 4 µs at 16 MHz,
## Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()
If you use a library which requires the same timer as IRremote, you have a problem, since **the timer resource cannot be shared simultaneously** by both libraries.
+### Use NEC protocol and TinyReceiver
+[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) does not require a timer, it relies on interrupts, thus avoiding any timer resource problems.
+
### Change timer
-The best approach is to change the timer used for IRremote, which can be accomplished by specifying the timer before `#include `.
+The best approach is to **change the timer** used for IRremote, which can be accomplished by specifying the timer before `#include `.
The timer specifications available for your board can be found in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp).
```c++
@@ -971,23 +1088,29 @@ The timer specifications available for your board can be found in [private/IRTim
Here you see the Arduino Mega board and the available specifications are `IR_USE_AVR_TIMER[1,2,3,4,5]`.
You **just have to include a line** e.g. `#define IR_USE_AVR_TIMER3` before `#include ` to enable timer 3.
-But be aware that the new timer in turn might be incompatible with other libraries or commands.
-For other boards/platforms you must look for the appropriate section guarded by e.g. `#elif defined(ESP32)`.
+But be aware that the new timer in turn might be again incompatible with other libraries or Arduino functions.
+For non AVR boards/platforms you must look for the appropriate section guarded by e.g. `#elif defined(ESP32)`.
### Stop and start timer
Another approach can be to share the timer **sequentially** if their functionality is used only for a short period of time like for the **Arduino tone() command**.
-An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), where the timer settings for IR receive are restored after the tone has stopped.
-For this we must call `IrReceiver.restartTimer()` or better `IrReceiver.restartTimer(microsecondsOfToneDuration)`.
-This only works since each call to` tone()` completely initializes the timer 2 used by the `tone()` command.
+An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298), where the IR timer is restarted after the tone has stopped.
+
+```c++
+IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
+tone(TONE_PIN, 2200, 8);
+delay(8);
+IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
+```
+This works on AVR boards like Uno because each call to` tone()` completely initializes the timer 2 used by the `tone()` command.
## Hardware-PWM signal generation for sending
If you define `SEND_PWM_BY_TIMER`, the send PWM signal is forced to be generated by a hardware timer on most platforms.
By default, the same timer as for the receiver is used.
Since each hardware timer has its dedicated output pin(s), you must change timer or timer sub-specifications to change PWM output pin. See [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp)
-**Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/39bdf8d7bf5b90dc221f8ae9fb3efed9f0a8a1db/examples/SimpleSender/PinDefinitionsAndMore.h#L273), where **PWM generation does not require a timer**.
+**Exceptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/PinDefinitionsAndMore.h#L341), where **PWM generation does not require a timer**.
## Why do we use 30% duty cycle for sending
-We [do it](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):
+We [do it](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRSend.hpp#L1194) according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf):
- Carrier duty cycle 50 %, peak current of emitter IF = 200 mA, the resulting transmission distance is 25 m.
- Carrier duty cycle 10 %, peak current of emitter IF = 800 mA, the resulting transmission distance is 29 m. - Factor 1.16
The reason is, that it is not the pure energy of the fundamental which is responsible for the receiver to detect a signal.
@@ -998,12 +1121,14 @@ Due to automatic gain control and other bias effects, high intensity of the 38 k
# How we decode signals
The IR signal is sampled at a **50 µs interval**. For a constant 525 µs pulse or pause we therefore get 10 or 11 samples, each with 50% probability.
And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
-Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
-E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
+Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L469-L491).
+E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0.
+This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space.
+For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
And since the receivers generated marks are longer or shorter than the spaces,
we have introduced the [`MARK_EXCESS_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) macro
-to compensate for this receiver (and signal strength as well as ambient light dependent :disappointed: ) specific deviation.
-Welcome to the world of **real world signal processing**.
+to compensate for this receiver and signal strength as well as ambient light dependent :disappointed: specific deviation.
+**Welcome to the world of real world signal processing**.
@@ -1019,7 +1144,7 @@ Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.
# Quick comparison of 5 Arduino IR receiving libraries
**This is a short comparison and may not be complete or correct.**
-I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.
+I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR library for my project and to have a quick overview, when to choose which library.
It is dated from **24.06.2022** and updated 10/2023. If you have complains about the data or request for extensions, please send a PM or open a discussion.
[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**.
@@ -1048,6 +1173,7 @@ It is dated from **24.06.2022** and updated 10/2023. If you have complains about
# [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md)
# Useful links
+- [Online NEC to Pronto converting tool](https://www.yamaha.com/ypab/irhex_converter.asp)
- [List of public IR code databases](http://www.harctoolbox.org/IR-resources.html)
- [LIRC database](http://lirc-remotes.sourceforge.net/remotes-table.html)
- [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols)
@@ -1069,4 +1195,4 @@ From the version 2.8.0, the license is the MIT license.
# Copyright
Initially coded 2009 Ken Shirriff http://www.righto.com
Copyright (c) 2016-2017 Rafi Khan https://rafikhan.io
-Copyright (c) 2020-2024 [Armin Joachimsmeyer](https://github.com/ArminJo)
+Copyright (c) 2020-2025 [Armin Joachimsmeyer](https://github.com/ArminJo)
diff --git a/changelog.md b/changelog.md
index ec69d2d6e..d76decdc6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -2,6 +2,43 @@
The latest version may not be released!
See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master
+# 4.5.0
+- Added support for multiple receiver instances.
+- irparams_struct irparams is now member of IRrecv. Thus removed rawDataPtr (pointer to irparams) from IrReceiver.decodedIRData.
+- Removed return value for all decodePulseDistanceWidthData() decoding functions, which returned a constant true.
+- New handling of MARK_EXCESS_MICROS without strange rounding inconsistency.
+- Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306.
+- Fixed minor bugs in Denon decoder.
+- Added threshold decoding.
+- Minor bug fixes for DEBUG.
+- LED feedback is always enabled for sending. It can only be disabled by using the macro NO_LED_SEND_FEEDBACK_CODE.
+- Removed parameter aEnableLEDFeedback in function IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) and IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin).
+- Added experimental sendVelux().
+- Added sendMaranz().
+- Added output for UNKNOWN protocol to printIRSendUsage().
+
+# 4.4.3
+- Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN to make the software aware of send LED connected between VCC and send pin.
+- Fixed backward compatibility bug for printIRResultShort(3 params).
+- Minor improvements.
+
+# 4.4.2
+- Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4).
+- attachInterrupt() on SAMD has a different semantic :-(. See: https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/.
+- Fixed overflow handling.
+- Improved repeat detection for DistanceWidthProtocol.
+- Print of IR frame duration in printIRResultShort();
+- PulseDistanceWidthProtocolConstants now in PROGMEM, this saves 190 bytes RAM for unit test.
+- Support for PROGMEM PulseDistanceWidthProtocol data.
+- Support duplicated 8 bit address for sendSamsungLG().
+
+# 4.4.1
+- Support for ESP core 3.x by akellai.
+- restartTimer() now uses variable sMicrosAtLastStopTimer to keep track of uncounted ticks between stopTimer() and restartTimer().
+- Removed functions addTicksToInternalTickCounter() and addMicrosToInternalTickCounter(), which were added in 4.1.0.
+- Version 2.2.0 of TinyIR with new TinyReceiverDecode() function to be used as drop in for IrReceiver.decode().
+- Support of RC6A.
+
# 4.4.0
- Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]).
- Renamed decodedIRData.initialGap to decodedIRData.initialGapTicks.
@@ -50,14 +87,14 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Usage of ATTinyCore pin numbering scheme e.g. PIN_PB2.
- Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense.
- First untested support of Uno R4.
-- Extraced version macros to IRVersion.h.
+- Extracted version macros to IRVersion.h.
## 4.1.2
- Workaround for ESP32 RTOS delay() timing bug influencing the mark() function.
## 4.1.1
- SAMD51 use timer3 if timer5 not available.
-- Disabled #define LOCAL_DEBUG in IRReceive.hpp, which was accidently enabled at 4.1.0.
+- Disabled #define LOCAL_DEBUG in IRReceive.hpp, which was accidentally enabled at 4.1.0.
## 4.1.0
- Fixed bug in printing durations > 64535 in printIRResultRawFormatted().
@@ -84,7 +121,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Introduced common structure PulseDistanceWidthProtocolConstants.
- Where possible, changed all send and decode functions to use PulseDistanceWidthProtocolConstants.
- Improved MSB/LSB handling
-- New convenience fuctions bitreverse32Bit() and bitreverseOneByte().
+- New convenience functions bitreverse32Bit() and bitreverseOneByte().
- Improved Magiquest protocol.
- Fix for #1028 - Prevent long delay caused by overflow when frame duration < repeat period - Thanks to Stephen Humphries!
- Support for ATtiny816 - Thanks to elockman.
@@ -128,7 +165,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Improved pin mapping for TinyReceiver.
## 3.7.1
-- SendRaw now supports bufferlenght > 255.
+- SendRaw now supports buffer length > 255.
- Improved DistanceProtocol decoder output.
- Fixed ESP32 send bug for 2.x ESP32 cores.
@@ -296,7 +333,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I
- Corrected keywords.txt.
- BoseWave protocol added PR #690.
- Formatting comply to the new stylesheet.
-- Renamed "boarddefs.h" [ISSUE #375](https://github.com/Arduino-IRremote/Arduino-IRremote/issues/375).
+- Renamed "boarddefs.h".
- Renamed `SEND_PIN` to `IR_SEND_PIN`.
- Renamed state macros.
- Enabled `DUTY_CYCLE` for send signal.
@@ -363,7 +400,7 @@ Changes from #268 by adamlhumphreys
- Fixed #110 Mess
- Created Gitter Room
- Added Gitter Badge
-- Standardised Code Base
+- Standardized Code Base
- Clean Debug Output
- Optimized Send Loops
- Modularized Design
@@ -391,4 +428,4 @@ Changes from #268 by adamlhumphreys
- Broke Teensy 3 / 3.1 Support
### Not Working
-- Teensy 3 / 3.1 Support is in Development
+- Teensy 3 / 3.1 Support is in Development
\ No newline at end of file
diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h
index c40621787..33c2bbfc1 100644
--- a/examples/AllProtocolsOnLCD/ADCUtils.h
+++ b/examples/AllProtocolsOnLCD/ADCUtils.h
@@ -29,6 +29,9 @@
#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
#define ADC_UTILS_ARE_AVAILABLE
+// External Reference Current is 150 uA for 5 V and 100 uA for 3.5 V
+#define READING_FOR_AREF 1024L // Datasheet 24.2: The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB
+
// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz
#define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE4 2 // 52 microseconds per ADC conversion at 1 MHz
diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp
index 73030b475..32355bee3 100644
--- a/examples/AllProtocolsOnLCD/ADCUtils.hpp
+++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp
@@ -27,11 +27,15 @@
#include "ADCUtils.h"
#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected
+#define ADC_UTILS_ARE_INCLUDED
-#if !defined(STR_HELPER)
+#if !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
+#if !defined(BITS_PER_BYTE)
+#define BITS_PER_BYTE 8
+#endif
/*
* By replacing this value with the voltage you measured a the AREF pin after a conversion
@@ -58,11 +62,16 @@ union WordUnionForADCUtils {
* 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)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
+#if defined(INFO)
+#define LOCAL_INFO
+#else
+//#define LOCAL_INFO // This enables debug output only for this file
+#endif
/*
* Persistent storage for VCC value
@@ -403,7 +412,7 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t
/*
* Get min and max of the last 4 values
*/
- tMin = 1024;
+ tMin = READING_FOR_AREF;
tMax = 0;
for (uint_fast8_t i = 0; i < 4; ++i) {
if (tValues[i] < tMin) {
@@ -472,7 +481,7 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t
float getVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- return ((1023 * 1.1 * 4) / tVCC);
+ return ((READING_FOR_AREF * 1.1 * 4) / tVCC);
}
/*
@@ -483,19 +492,19 @@ float getVCCVoltageSimple(void) {
uint16_t getVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
+ return ((READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
}
/*
* Gets the hypothetical 14 bit reading of VCC using 1.1 volt reference
- * Similar to getVCCVoltageMillivolt() * 1023 / 1100
+ * Similar to getVCCVoltageMillivolt() * 1024 / 1100
*/
uint16_t getVCCVoltageReadingFor1_1VoltReference(void) {
uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
- return ((1023L * 1023L) / tVCC);
+ return ((READING_FOR_AREF * READING_FOR_AREF) / tVCC);
}
/*
@@ -519,7 +528,7 @@ uint16_t getVCCVoltageMillivolt(void) {
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
- return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
+ return ((READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
}
/*
@@ -547,7 +556,7 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
void readVCCVoltageSimple(void) {
// use AVCC with (optional) external capacitor at AREF pin as reference
float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- sVCCVoltage = (1023 * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
+ sVCCVoltage = (READING_FOR_AREF * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}
/*
@@ -558,7 +567,7 @@ void readVCCVoltageSimple(void) {
void readVCCVoltageMillivoltSimple(void) {
// use AVCC with external capacitor at AREF pin as reference
uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
- sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
+ sVCCVoltageMillivolt = (READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}
/*
@@ -579,7 +588,7 @@ void readVCCVoltageMillivolt(void) {
/*
* Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
*/
- sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
+ sVCCVoltageMillivolt = (READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
}
/*
@@ -588,7 +597,7 @@ void readVCCVoltageMillivolt(void) {
*/
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
- return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / 1023;
+ return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
@@ -597,16 +606,18 @@ uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelF
*/
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
- return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / 1023;
+ return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement) {
uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, INTERNAL);
- return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / 1023;
+ return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}
/*
* Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
+ * This does not really work for the UNO board, because it has no series Diode in the USB VCC
+ * and therefore a very low voltage drop.
*/
bool isVCCUSBPowered() {
readVCCVoltageMillivolt();
@@ -634,13 +645,13 @@ bool isVCCUSBPowered(Print *aSerial) {
}
/*
+ * It checks every 10 seconds for 6 times, and then returns true if the undervoltage condition ( <3.4V ) still applies.
* @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown
*/
bool isVCCUndervoltageMultipleTimes() {
/*
* Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds
*/
-
if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
sLastVCCCheckMillis = millis();
@@ -650,30 +661,32 @@ bool isVCCUndervoltageMultipleTimes() {
readVCCVoltageMillivolt();
# endif
- if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
- /*
- * Do not check again if shutdown has happened
- */
+ /*
+ * Do not check again if shutdown signaling (sVCCTooLowCounter >= 6) has happened
+ */
+ if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) { // VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP = 6
if (sVCCVoltageMillivolt > VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
sVCCTooLowCounter = 0; // reset counter
} else {
/*
- * Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then shut down.
+ * Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then signal shut down.
*/
if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
// emergency shutdown
sVCCTooLowCounter = VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP;
-# if defined(INFO)
+# if defined(LOCAL_INFO)
Serial.println(
F(
- "Voltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown"));
+ "Undervoltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown"));
# endif
} else {
sVCCTooLowCounter++;
-# if defined(INFO)
- Serial.print(F("Voltage < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected: "));
+# if defined(LOCAL_INFO)
+ Serial.print(sVCCVoltageMillivolt);
+ Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV undervoltage detected: "));
+
Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter);
- Serial.println(F(" tries left"));
+ Serial.println(F(" attempts left"));
# endif
}
if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
@@ -815,4 +828,7 @@ float getVCCVoltage() {
#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
+#if defined(LOCAL_INFO)
+#undef LOCAL_INFO
+#endif
#endif // _ADC_UTILS_HPP
diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
index ed9e18cdf..668922eb8 100644
--- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
+++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2024 Armin Joachimsmeyer
+ * Copyright (c) 2022-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,7 +36,7 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
# else
@@ -59,10 +59,12 @@
#endif
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 120 bytes program memory.
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
@@ -123,7 +125,7 @@ bool ProtocolStringOverwritesVoltage = false;
void printsVCCVoltageMillivoltOnLCD();
void printIRResultOnLCD();
size_t printByteHexOnLCD(uint16_t aHexByteValue);
-void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint);
+void printSpacesOnLCD(int_fast8_t aNumberOfSpacesToPrint);
#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
@@ -137,8 +139,6 @@ void setup() {
#endif
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -185,8 +185,13 @@ void setup() {
// Info for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
@@ -240,7 +245,7 @@ void loop() {
} else {
// play tone
auto tStartMillis = millis();
- IrReceiver.stopTimer();
+// IrReceiver.stopTimer(); // Not really required for Uno, but we then should use restartTimer(aMicrosecondsToAddToGapCounter)
tone(TONE_PIN, 2200);
if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW)
@@ -259,9 +264,7 @@ void loop() {
while ((millis() - tStartMillis) < 5)
;
noTone(TONE_PIN);
-
- // Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement.
- IrReceiver.restartTimerWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
+ IrReceiver.restartTimer(5000); // Restart IR timer.
#if defined(USE_LCD)
printIRResultOnLCD();
@@ -287,11 +290,11 @@ void loop() {
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
printsVCCVoltageMillivoltOnLCD();
#endif
- IrReceiver.stopTimer();
+// IrReceiver.stopTimer(); // Not really required for Uno, but we then should use restartTimer(aMicrosecondsToAddToGapCounter)
tone(TONE_PIN, 2200);
delay(50);
noTone(TONE_PIN);
- IrReceiver.restartTimerWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK));
+ IrReceiver.restartTimer(50000);
}
#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
@@ -367,21 +370,18 @@ void printIRResultOnLCD() {
* 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;
+ uint8_t tNumberOfBits = (IrReceiver.irparams.rawlen + 1) / 2;
uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits);
myLCD.print(F(" bit "));
- if (IrReceiver.decodedIRData.decodedRawData != 0) {
- if (tNumberOfBits < 10) {
- myLCD.print('0');
- tPrintedStringLength++;
- }
+ if (tNumberOfBits < 10) {
+ myLCD.print('0');
+ tPrintedStringLength++;
+ }
+ if (tNumberOfBits < 100) {
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
}
+ tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX) + 1;
printSpacesOnLCD(11 - tPrintedStringLength);
sLastProtocolAddress = 4711;
sLastCommand = 44711;
@@ -389,7 +389,7 @@ void printIRResultOnLCD() {
} else {
/*
* Protocol is know here
- * Print address only if it has changed
+ * Print address only if it has changed or is PULSE_DISTANCE or PULSE_WIDTH
*/
if (sLastProtocolAddress != IrReceiver.decodedIRData.address || IrReceiver.decodedIRData.protocol == PULSE_DISTANCE
|| IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
@@ -476,9 +476,11 @@ size_t printByteHexOnLCD(uint16_t aHexByteValue) {
return myLCD.print(aHexByteValue, HEX) + tPrintSize;
}
-void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint) {
- for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
- myLCD.print(' ');
+void printSpacesOnLCD(int_fast8_t aNumberOfSpacesToPrint) {
+ if (aNumberOfSpacesToPrint > 0) {
+ for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) {
+ myLCD.print(' ');
+ }
}
}
#endif // defined(USE_LCD)
diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
index 5dcef0838..240524a95 100644
--- a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
+++ b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp
@@ -5,6 +5,20 @@
#include
#include "Arduino.h"
+#if defined(__AVR__)
+/*
+ * The datasheet says: a command need > 37us to settle.
+ * Use a delay of 2 us instead of 100 us after each command,
+ * because the overhead of this library seems to be using the other 35 us.
+ * At least it works perfectly for all my LCD's connected to Uno, Nano etc.
+ * and it saves a lot of time in realtime applications using LCD as display,
+ * like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter
+ */
+# if !defined(DO_NOT_USE_FAST_LCD_TIMING)
+#define USE_FAST_LCD_TIMING
+# endif
+#endif
+
// When the display powers up, it is configured as follows:
//
// 1. Display clear
@@ -21,7 +35,7 @@
// S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
-// can't assume that its in that state when a sketch starts (and the
+// can't assume that it is in that state when a sketch starts (and the
// LiquidCrystal constructor is called).
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
@@ -72,7 +86,7 @@ void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t en
else
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
- begin(16, 1);
+ begin(16, 1); // initializing for a 1601 LCD, but the user must call begin() with the right values at startup. Outcommenting increases program size
}
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
@@ -262,12 +276,14 @@ void LiquidCrystal::noAutoscroll(void) {
// Allows us to fill the first 8 CGRAM locations
// with custom characters
+// This also sets cursor to 0.0
void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
}
+ // command(LCD_SETDDRAMADDR); // set cursor to 0.0, this avoids overwriting CGRAM by next write() command. Not contained anymore in the Arduino version
}
/*********** mid level commands, for sending data/cmds */
@@ -278,7 +294,7 @@ inline void LiquidCrystal::command(uint8_t value) {
inline size_t LiquidCrystal::write(uint8_t value) {
send(value, HIGH);
- return 1; // assume sucess
+ return 1; // assume success
}
/************ low level data pushing commands **********/
@@ -306,7 +322,11 @@ void LiquidCrystal::pulseEnable(void) {
digitalWrite(_enable_pin, HIGH);
delayMicroseconds(1); // enable pulse must be >450ns
digitalWrite(_enable_pin, LOW);
+#if defined(USE_FAST_LCD_TIMING)
+ delayMicroseconds(2); // commands need > 37us to settle
+#else
delayMicroseconds(100); // commands need > 37us to settle
+#endif
}
void LiquidCrystal::write4bits(uint8_t value) {
diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
+++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ControlRelay/ControlRelay.ino b/examples/ControlRelay/ControlRelay.ino
index 346b13b34..0ea2e73aa 100644
--- a/examples/ControlRelay/ControlRelay.ino
+++ b/examples/ControlRelay/ControlRelay.ino
@@ -53,8 +53,6 @@ void setup() {
pinMode(RELAY_PIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ControlRelay/PinDefinitionsAndMore.h
+++ b/examples/ControlRelay/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp
index 701103a1f..a8006400e 100644
--- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp
+++ b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp
@@ -59,7 +59,7 @@
#else
//#define LOCAL_INFO // This enables info output only for this file
#endif
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
// Propagate debug level
#define LOCAL_INFO
@@ -78,7 +78,7 @@ IRCommandDispatcher IRDispatcher;
#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.
+#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // included in "IRremote" library
void IRCommandDispatcher::init() {
diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino
index fda2a2c57..6df3321ab 100644
--- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino
+++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino
@@ -109,8 +109,6 @@ void doTone2200();
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
+++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
index 8a315e9c7..9f1a73401 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2021-2024 Armin Joachimsmeyer
+ * Copyright (c) 2021-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,10 +36,10 @@
* 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 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
-# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
+# else
#define RAW_BUFFER_LENGTH 750
# endif
#endif
@@ -53,8 +53,8 @@ bool IRExtensionClass::decode() {
return MyIrReceiver->decode();
}
-bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
- return MyIrReceiver->printIRResultShort(aSerial, aPrintRepeatGap, aCheckForRecordGapsMicros);
+bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) {
+ return MyIrReceiver->printIRResultShort(aSerial, aCheckForRecordGapsMicros);
}
void IRExtensionClass::resume() {
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
index 2fa648a7c..07c858802 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2021-2024 Armin Joachimsmeyer
+ * Copyright (c) 2021-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -40,7 +40,7 @@ class IRExtensionClass
IRrecv * MyIrReceiver;
IRExtensionClass(IRrecv * aIrReceiver);
bool decode();
- bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap = true, bool aCheckForRecordGapsMicros = true);
+ bool printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros = true);
void resume();
};
diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
index 3ec197ad8..50bea009f 100644
--- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
+++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino
@@ -33,7 +33,7 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
# else
@@ -52,12 +52,15 @@ IRExtensionClass IRExtension(&IrReceiver);
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
+++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino
index 31d037668..25d0f09d9 100644
--- a/examples/IRremoteInfo/IRremoteInfo.ino
+++ b/examples/IRremoteInfo/IRremoteInfo.ino
@@ -34,13 +34,17 @@ void dumpFooter();
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
+
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino
index a5bcae2b8..194728d32 100644
--- a/examples/MicroGirs/MicroGirs.ino
+++ b/examples/MicroGirs/MicroGirs.ino
@@ -67,7 +67,7 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
# else
@@ -82,6 +82,8 @@
#define BAUDRATE 115200
#define NO_DECODER
+//#define NO_LED_FEEDBACK_CODE // Saves 346 bytes program memory
+
#include "IRremote.hpp"
#include
@@ -258,13 +260,13 @@ static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, const mi
#if defined(RECEIVE)
static void dump(Stream &stream) {
- unsigned int count = IrReceiver.decodedIRData.rawDataPtr->rawlen;
+ unsigned int count = IrReceiver.irparams.rawlen;
// If buffer gets full, count = RAW_BUFFER_LENGTH, which is odd,
// and IrScrutinizer does not like that.
count &= ~1;
for (unsigned int i = 1; i < count; i++) {
stream.write(i & 1 ? '+' : '-');
- stream.print(IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK, DEC);
+ stream.print(IrReceiver.irparams.rawbuf[i] * MICROS_PER_TICK, DEC);
stream.print(" ");
}
stream.print('-');
@@ -292,8 +294,6 @@ static void receive(Stream &stream) {
*/
void setup() {
Serial.begin(BAUDRATE);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
Serial.println(F(PROGNAME " " VERSION));
// Just to know which program is running on my Arduino
@@ -309,9 +309,13 @@ void setup() {
#endif
#if defined(IR_SEND_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
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
#else
- IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin
+ IrSender.begin(3); // Specify send pin and enable feedback LED at default feedback LED pin
#endif
}
diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/MicroGirs/PinDefinitionsAndMore.h
+++ b/examples/MicroGirs/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino
new file mode 100644
index 000000000..254db7e1e
--- /dev/null
+++ b/examples/MultipleReceivers/MultipleReceivers.ino
@@ -0,0 +1,148 @@
+/*
+ * MultipleReceivers.cpp
+ *
+ * Demonstrates receiving from multiple receivers at different pins using multiple IRreceiver instances
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ ************************************************************************************
+ * MIT License
+ *
+ * Copyright (c) 2025 Armin Joachimsmeyer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ ************************************************************************************
+ */
+
+#include
+
+#define IR_RECEIVE_PIN_OF_SECOND_RECEIVER 5
+
+/*
+ * Specify which protocol(s) should be used for decoding.
+ * If no protocol is defined, all protocols (except Bang&Olufsen) are active.
+ * This must be done before the #include
+ */
+//#define DECODE_DENON // Includes Sharp
+//#define DECODE_JVC
+//#define DECODE_KASEIKYO
+//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
+//#define DECODE_LG
+//#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
+//#define DECODE_SAMSUNG
+//#define DECODE_SONY
+//#define DECODE_RC5
+//#define DECODE_RC6
+//#define DECODE_BOSEWAVE
+//#define DECODE_LEGO_PF
+//#define DECODE_MAGIQUEST
+//#define DECODE_WHYNTER
+//#define DECODE_FAST
+//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
+//#define DECODE_HASH // special decoder for all protocols
+//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY!
+//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
+#define SUPPORT_MULTIPLE_RECEIVER_INSTANCES
+void UserIRReceiveTimerInterruptHandler(); // must also be before line #include
+
+/*
+ * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
+ */
+#include "PinDefinitionsAndMore.h"
+#include // include the library
+
+IRrecv MySecondIrReceiver(IR_RECEIVE_PIN_OF_SECOND_RECEIVER); // This sets the pin for the second instance
+
+void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance);
+
+void setup() {
+ Serial.begin(115200);
+
+ // Just to know which program is running on my Arduino
+ Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
+
+ // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED
+ IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // This sets the pin for the default / first instance and enables the global LED feedback
+
+ Serial.print(F("Ready to receive IR signals of protocols: "));
+ printActiveIRProtocols(&Serial);
+ Serial.println(F("at pin " STR(IR_RECEIVE_PIN) " and pin " STR(IR_RECEIVE_PIN_OF_SECOND_RECEIVER)));
+}
+
+void loop() {
+ /*
+ * Check if received data is available and if yes, try to decode it.
+ * Decoded result is in the IrReceiver.decodedIRData structure.
+ *
+ * E.g. command is in IrReceiver.decodedIRData.command
+ * address is in command is in IrReceiver.decodedIRData.address
+ * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData
+ */
+ if (IrReceiver.decode()) {
+ handleSuccessfulDecoding(&IrReceiver);
+ }
+ if (MySecondIrReceiver.decode()) {
+ handleSuccessfulDecoding(&MySecondIrReceiver);
+ }
+}
+
+void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance) {
+
+ Serial.print(F("Receiver at pin "));
+ Serial.print(aIRReceiverInstance->irparams.IRReceivePin);
+ Serial.print(F(": "));
+
+ /*
+ * Print a summary of received data
+ */
+ if (aIRReceiverInstance->decodedIRData.protocol == UNKNOWN) {
+ Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
+ // We have an unknown protocol here, print extended info
+ aIRReceiverInstance->printIRResultRawFormatted(&Serial, true);
+
+ aIRReceiverInstance->resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted()
+ } else {
+ aIRReceiverInstance->resume(); // Early enable receiving of the next IR frame
+
+ aIRReceiverInstance->printIRResultShort(&Serial);
+ aIRReceiverInstance->printIRSendUsage(&Serial);
+ }
+ Serial.println();
+
+ /*
+ * Finally, check the received data and perform actions according to the received command
+ */
+ if (aIRReceiverInstance->decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (aIRReceiverInstance->decodedIRData.command == 0x10) {
+ Serial.println(F("Received command 0x10."));
+ // do something
+ } else if (aIRReceiverInstance->decodedIRData.command == 0x11) {
+ Serial.println(F("Received command 0x11."));
+ // do something else
+ }
+ }
+
+}
+
+void UserIRReceiveTimerInterruptHandler() {
+ MySecondIrReceiver.ReceiveInterruptHandler();
+}
diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h
new file mode 100644
index 000000000..907e2a641
--- /dev/null
+++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h
@@ -0,0 +1,359 @@
+/*
+ * 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 .
+ *
+ */
+
+/*
+ * Pin mapping table for different platforms
+ *
+ * Platform IR input IR output Tone Core/Pin schema
+ * --------------------------------------------------------------
+ * DEFAULT/AVR 2 3 4 Arduino
+ * ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore
+ * ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore
+ * ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
+ * ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
+ * ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
+ * ATtiny1604 2 3|PA5 %
+ * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
+ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
+ * MKR* 1 3 4
+ * SAMD 2 3 4
+ * ESP8266 14|D5 12|D6 %
+ * ESP32 15 4 27
+ * ESP32-C3 2 3 4
+ * BluePill PA6 PA7 PA3
+ * APOLLO3 11 12 5
+ * RP2040 3|GPIO15 4|GPIO16 5|GPIO17
+ */
+//#define _IR_MEASURE_TIMING // For debugging purposes.
+
+#if defined(__AVR__)
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
+#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
+#define IR_RECEIVE_PIN PIN_PB0
+#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
+#define TONE_PIN PIN_PB3
+#define _IR_TIMING_TEST_PIN PIN_PB3
+
+# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
+#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
+// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
+// For use with Digispark original core
+#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
+//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
+#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
+#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
+#define _IR_TIMING_TEST_PIN 10 // PA4
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
+// For use with ATTinyCore
+#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
+#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
+#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
+# endif
+
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
+#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
+#define IR_RECEIVE_PIN PIN_PB2 // INT0
+#define IR_SEND_PIN PIN_PA4
+#define TONE_PIN PIN_PA3
+#define _IR_TIMING_TEST_PIN PIN_PA5
+
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
+#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
+// Pin 6 is TX, pin 7 is RX
+#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
+#define IR_SEND_PIN PIN_PD4 // 4
+#define TONE_PIN PIN_PB1 // 9
+#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
+
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
+// Tiny Core Dev board
+// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock
+// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
+#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
+#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
+
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
+#define IR_RECEIVE_PIN PIN_PA1 // 14
+#define IR_SEND_PIN PIN_PA3 // 16
+#define TONE_PIN PIN_PA5 // 1
+#define APPLICATION_PIN PIN_PA4 // 0
+#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
+#define LED_BUILTIN PIN_PB5 // 4
+
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
+#define IR_RECEIVE_PIN PIN_PA1 // 8
+#define IR_SEND_PIN PIN_PA3 // 10
+#define TONE_PIN PIN_PA5 // 1
+#define APPLICATION_PIN PIN_PA4 // 0
+
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
+
+#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
+#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
+#define IR_RECEIVE_PIN 6
+#define IR_SEND_PIN 7
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
+
+#elif defined(ESP32)
+#include
+
+// tone() is included in ESP32 core since 2.0.2
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
+#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
+#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
+void tone(uint8_t aPinNumber, unsigned int aFrequency){
+ ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
+ ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
+}
+void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
+ ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
+ ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
+ delay(aDuration);
+ ledcWriteTone(TONE_LEDC_CHANNEL, 0);
+}
+void noTone(uint8_t aPinNumber){
+ ledcWriteTone(TONE_LEDC_CHANNEL, 0);
+}
+#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
+
+#define IR_RECEIVE_PIN 15 // D15
+#define IR_SEND_PIN 4 // D4
+#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
+#define APPLICATION_PIN 16 // RX2 pin
+
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
+// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
+#define IR_RECEIVE_PIN PA6
+#define IR_RECEIVE_PIN_STRING "PA6"
+#define IR_SEND_PIN PA7
+#define IR_SEND_PIN_STRING "PA7"
+#define TONE_PIN PA3
+#define _IR_TIMING_TEST_PIN PA5
+#define APPLICATION_PIN PA2
+#define APPLICATION_PIN_STRING "PA2"
+# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8)
+// BluePill LED is active low
+#define FEEDBACK_LED_IS_ACTIVE_LOW
+# endif
+
+#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards
+#define IR_RECEIVE_PIN 11
+#define IR_SEND_PIN 12
+#define TONE_PIN 5
+
+#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED
+// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect
+#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
+#define IR_SEND_PIN 4 // GPIO16
+#define TONE_PIN 5
+#define APPLICATION_PIN 6
+#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output.
+#define _IR_TIMING_TEST_PIN 8
+
+#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
+#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3)
+#define IR_SEND_PIN 16 // GPIO16
+#define TONE_PIN 17
+#define APPLICATION_PIN 18
+#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output.
+#define _IR_TIMING_TEST_PIN 20
+
+// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
+// and use the external reset with 1 kOhm to ground to enter UF2 mode
+#undef LED_BUILTIN
+#define LED_BUILTIN 6
+
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
+#define IR_RECEIVE_PIN A4
+#define IR_SEND_PIN A5 // Particle supports multiple pins
+
+#define LED_BUILTIN D7
+
+/*
+ * 4 times the same (default) layout for easy adaption in the future
+ */
+#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc.
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 5
+#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
+#define _IR_TIMING_TEST_PIN 7
+
+#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 5
+#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
+#define _IR_TIMING_TEST_PIN 7
+
+#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
+#define IR_RECEIVE_PIN 2
+# endif
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 5
+#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
+#define _IR_TIMING_TEST_PIN 7
+
+#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0)
+// On the Zero and others we switch explicitly to SerialUSB
+#define Serial SerialUSB
+#endif
+
+// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
+// Attention!!! D2 and D4 are swapped on these boards!!!
+// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
+//#undef LED_BUILTIN
+//#define LED_BUILTIN 24 // PB11
+// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
+//#undef LED_BUILTIN
+//#define LED_BUILTIN 25 // PB03
+//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW
+
+#elif defined (NRF51) // BBC micro:bit
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define APPLICATION_PIN 1
+#define _IR_TIMING_TEST_PIN 4
+
+#define tone(...) void() // no tone() available
+#define noTone(a) void()
+#define TONE_PIN 42 // Dummy for examples using it
+
+#else
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, 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
diff --git a/examples/MultipleSendPins/MultipleSendPins.ino b/examples/MultipleSendPins/MultipleSendPins.ino
new file mode 100644
index 000000000..30a627ef7
--- /dev/null
+++ b/examples/MultipleSendPins/MultipleSendPins.ino
@@ -0,0 +1,96 @@
+/*
+ * MultipleSendPins.cpp
+ *
+ * Demonstrates sending IR codes toggling between 2 different send pins.
+ * Based on SimpleSender.
+ *
+ * Copyright (C) 2025 Armin Joachimsmeyer
+ * armin.joachimsmeyer@gmail.com
+ *
+ * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
+ *
+ * MIT License
+ */
+#include
+
+#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
+#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
+#endif
+
+//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 52 bytes program memory
+
+#include // include the library
+
+void setup() {
+ pinMode(LED_BUILTIN, OUTPUT);
+
+ Serial.begin(115200);
+
+ // Just to know which program is running on my Arduino
+ Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
+ Serial.print(F("Send IR signals alternating at pin 3 and 4"));
+
+ /*
+ * The IR library setup. That's all!
+ */
+ IrSender.begin(3); // Start with pin3 as send pin and enable feedback LED at default feedback LED pin
+ disableLEDFeedback(); // Disable feedback LED at default feedback LED pin
+}
+
+/*
+ * Set up the data to be sent.
+ * For most protocols, the data is build up with a constant 8 (or 16 byte) address
+ * and a variable 8 bit command.
+ * There are exceptions like Sony and Denon, which have 5 bit address.
+ */
+uint8_t sCommand = 0x34;
+uint8_t sRepeats = 0;
+
+void loop() {
+ /*
+ * Print current send values
+ */
+ Serial.println();
+ Serial.print(F("Send now: address=0x00, command=0x"));
+ Serial.print(sCommand, HEX);
+ Serial.print(F(", repeats="));
+ Serial.print(sRepeats);
+ Serial.println();
+
+ Serial.println(F("Send standard NEC with 8 bit address"));
+ Serial.flush();
+
+ // Receiver output for the first loop must be: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits)
+ IrSender.sendNEC(0x00, sCommand, sRepeats);
+
+ /*
+ * If you want to send a raw HEX value directly like e.g. 0xCB340102 you must use sendNECRaw()
+ */
+// Serial.println(F("Send 32 bit LSB 0xCB340102 with NECRaw()"));
+// IrSender.sendNECRaw(0xCB340102, sRepeats);
+ /*
+ * If you want to send an "old" MSB HEX value used by IRremote versions before 3.0 like e.g. 0x40802CD3 you must use sendNECMSB()
+ */
+// Serial.println(F("Send old 32 bit MSB 0x40802CD3 with sendNECMSB()"));
+// IrSender.sendNECMSB(0x40802CD3, 32, sRepeats);
+ /*
+ * Increment send values
+ */
+ sCommand += 0x11;
+ sRepeats++;
+ // clip repeats at 4
+ if (sRepeats > 4) {
+ sRepeats = 4;
+ }
+
+ /*
+ * Toggle between send pin 3 and 4
+ */
+ if (IrSender.sendPin == 3) {
+ IrSender.setSendPin(4);
+ } else {
+ IrSender.setSendPin(3);
+ }
+ delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal
+}
diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h
+++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino
index ee4dc7519..a104f9106 100644
--- a/examples/ReceiveAndSend/ReceiveAndSend.ino
+++ b/examples/ReceiveAndSend/ReceiveAndSend.ino
@@ -23,7 +23,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2009-2024 Ken Shirriff, Armin Joachimsmeyer
+ * Copyright (c) 2009-2025 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
@@ -58,7 +58,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
//#define DECODE_SAMSUNG
//#define DECODE_SONY
//#define DECODE_RC5
@@ -72,22 +72,24 @@
//
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF))
-#define RAW_BUFFER_LENGTH 750
+#define RAW_BUFFER_LENGTH 700 // we require 2 buffer of this size for this example
# endif
#endif
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
-//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active
+#define 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 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 202 bytes program memory
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@@ -114,8 +116,6 @@ void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -130,9 +130,14 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("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.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
- Serial.println(SEND_BUTTON_PIN);
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
+ Serial.print(F("Ready to send IR signal (with repeats) at pin " STR(IR_SEND_PIN) " as long as button at pin "));
+ Serial.print(SEND_BUTTON_PIN);
+ Serial.println(F(" is pressed."));
}
void loop() {
@@ -169,6 +174,7 @@ void loop() {
// Restart receiver
Serial.println(F("Button released -> start receiving"));
IrReceiver.start();
+ delay(100); // Button debouncing
} else if (IrReceiver.decode()) {
/*
@@ -179,15 +185,14 @@ void loop() {
}
sSendButtonWasActive = tSendButtonIsActive;
- delay(100);
}
// Stores the code for later playback in sStoredIRData
// Most of this code is just logging
void storeCode() {
- if (IrReceiver.decodedIRData.rawDataPtr->rawlen < 4) {
+ if (IrReceiver.irparams.rawlen < 4) {
Serial.print(F("Ignore data with rawlen="));
- Serial.println(IrReceiver.decodedIRData.rawDataPtr->rawlen);
+ Serial.println(IrReceiver.irparams.rawlen);
return;
}
if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
@@ -202,21 +207,31 @@ void storeCode() {
Serial.println(F("Ignore parity error"));
return;
}
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
+ Serial.println(F("Overflow occurred, raw data did not fit into " STR(RAW_BUFFER_LENGTH) " byte raw buffer"));
+ return;
+ }
/*
* Copy decoded data
*/
sStoredIRData.receivedIRData = IrReceiver.decodedIRData;
- if (sStoredIRData.receivedIRData.protocol == UNKNOWN) {
- Serial.print(F("Received unknown code and store "));
- Serial.print(IrReceiver.decodedIRData.rawDataPtr->rawlen - 1);
- Serial.println(F(" timing entries as raw "));
- IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
- sStoredIRData.rawCodeLength = IrReceiver.decodedIRData.rawDataPtr->rawlen - 1;
+ auto tProtocol = sStoredIRData.receivedIRData.protocol;
+ if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE) {
+ // TODO: support PULSE_WIDTH and PULSE_DISTANCE with IrSender.write
+ sStoredIRData.rawCodeLength = IrReceiver.irparams.rawlen - 1;
/*
* Store the current raw data in a dedicated array for later usage
*/
IrReceiver.compensateAndStoreIRResultInArray(sStoredIRData.rawCode);
+ /*
+ * Print info
+ */
+ Serial.print(F("Received unknown or pulse width/distance code and store "));
+ Serial.print(IrReceiver.irparams.rawlen - 1);
+ Serial.println(F(" timing entries as raw in buffer of size " STR(RAW_BUFFER_LENGTH)));
+ IrReceiver.printIRResultRawFormatted(&Serial, true); // Output the results in RAW format
+
} else {
IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRSendUsage(&Serial);
@@ -226,7 +241,8 @@ void storeCode() {
}
void sendCode(storedIRDataStruct *aIRDataToSend) {
- if (aIRDataToSend->receivedIRData.protocol == UNKNOWN /* i.e. raw */) {
+ auto tProtocol = aIRDataToSend->receivedIRData.protocol;
+ if (tProtocol == UNKNOWN || tProtocol == PULSE_WIDTH || tProtocol == PULSE_DISTANCE /* i.e. raw */) {
// Assume 38 KHz
IrSender.sendRaw(aIRDataToSend->rawCode, aIRDataToSend->rawCodeLength, 38);
@@ -234,12 +250,11 @@ void sendCode(storedIRDataStruct *aIRDataToSend) {
Serial.print(aIRDataToSend->rawCodeLength);
Serial.println(F(" marks or spaces"));
} else {
-
/*
* Use the write function, which does the switch for different protocols
*/
IrSender.write(&aIRDataToSend->receivedIRData);
- printIRResultShort(&Serial, &aIRDataToSend->receivedIRData, false);
+ printIRDataShort(&Serial, &aIRDataToSend->receivedIRData);
}
}
diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
+++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
index c0d9da014..dac652bb4 100644
--- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
+++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino
@@ -23,7 +23,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2023 Armin Joachimsmeyer
+ * Copyright (c) 2023-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -57,7 +57,7 @@
#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)
#define RAW_BUFFER_LENGTH 360
# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
@@ -69,6 +69,9 @@
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 218 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 82 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 58 bytes program memory
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@@ -79,8 +82,8 @@
#define DELAY_BETWEEN_REPEATS_MILLIS 70
// Storage for the recorded code, pre-filled with NEC data
-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
+IRRawDataType sDecodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34
+DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing
uint8_t sNumberOfBits = 32;
bool sSendButtonWasActive;
@@ -89,8 +92,6 @@ void setup() {
pinMode(SEND_BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -103,7 +104,11 @@ void setup() {
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin "));
Serial.println(SEND_BUTTON_PIN);
}
diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h
+++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino
index 159dad611..5ffd427e4 100644
--- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino
+++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino
@@ -34,8 +34,11 @@
#define DECODE_HASH // Only decoder, which works for Hob2Hood. protocol is UNKNOWN and only raw data is set.
-//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
-//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
+//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory
+//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
+//#define NO_LED_FEEDBACK_CODE // Saves 310 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 44 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 34 bytes program memory
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include
@@ -74,8 +77,6 @@ const uint16_t *const Hob2HoodSendCommands[NUMBER_OF_HOB_TO_HOOD_COMMANDS] = { F
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -88,7 +89,11 @@ void setup() {
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
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Send Hob2Hood IR signals at pin " STR(IR_SEND_PIN)));
}
diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveDemo/PinDefinitionsAndMore.h
+++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino
index 7a56be84f..4b44fc3d8 100644
--- a/examples/ReceiveDemo/ReceiveDemo.ino
+++ b/examples/ReceiveDemo/ReceiveDemo.ino
@@ -10,7 +10,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2024 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -48,7 +48,6 @@
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
//#define DECODE_LG
-//#define DECODE_ONKYO // Decodes only Onkyo and not NEC or Apple
//#define DECODE_NEC // Includes Apple and Onkyo
//#define DECODE_SAMSUNG
//#define DECODE_SONY
@@ -61,19 +60,33 @@
//#define DECODE_FAST
//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
//#define DECODE_HASH // special decoder for all protocols
+//#define DECODE_ONKYO // Disables NEC and Apple
//#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!
-#endif
-#if defined(DECODE_BEO)
-#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer, but this prevents decoding of SONY!
+#else
+// for 8k flash
+//#define DECODE_DENON // Includes Sharp
+#define DECODE_JVC
+#define DECODE_KASEIKYO
+#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
+#define DECODE_LG
+#define DECODE_NEC // Includes Apple and Onkyo
+#define DECODE_SAMSUNG
+//#define DECODE_SONY
+//#define DECODE_RC5
+//#define DECODE_RC6
+#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols
+#define DECODE_HASH // special decoder for all protocols
+
+#define EXCLUDE_EXOTIC_PROTOCOLS
#endif
// etc. see IRremote.hpp
//
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF))
#define RAW_BUFFER_LENGTH 750
# endif
@@ -82,23 +95,33 @@
//#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 USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 1 bytes program memory.
//#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory
// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
+#if defined(DECODE_BEO)
+#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer, but this prevents decoding of SONY!
+#endif
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
#include
-#if defined(APPLICATION_PIN)
-#define DEBUG_BUTTON_PIN APPLICATION_PIN // if low, print timing for each received data set
+#if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN)
+#define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data
#else
#define DEBUG_BUTTON_PIN 6
#endif
+#if defined(ESP32) && defined(DEBUG_BUTTON_PIN)
+# if !digitalPinIsValid(DEBUG_BUTTON_PIN)
+#undef DEBUG_BUTTON_PIN // DEBUG_BUTTON_PIN number is not valid, so delete definition to disable further usage
+# endif
+#endif
void generateTone();
void handleOverflow();
@@ -106,17 +129,18 @@ bool detectLongPress(uint16_t aLongPressDurationMillis);
void setup() {
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+# if defined(DEBUG_BUTTON_PIN)
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
+# endif
#endif
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
- || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
+ || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) || (defined(ESP32) && defined(ARDUINO_USB_MODE))
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
+
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -135,25 +159,33 @@ void setup() {
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#endif
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
Serial.println();
- if (digitalRead(DEBUG_BUTTON_PIN) != LOW) {
- Serial.print(F("If you connect debug pin "));
-# if defined(APPLICATION_PIN_STRING)
- Serial.print(APPLICATION_PIN_STRING);
-# else
- Serial.print(DEBUG_BUTTON_PIN);
+# if defined(DEBUG_BUTTON_PIN)
+ Serial.print(F("If you connect debug pin "));
+ Serial.print(DEBUG_BUTTON_PIN);
+ Serial.println(F(" to ground, raw data is always printed and tone is disabled"));
# endif
- Serial.print(F(" to ground, "));
- }
- Serial.println(F("raw data is always printed"));
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
-#endif
+# endif
+#endif // FLASHEND >= 0x3FFF
}
void loop() {
@@ -167,8 +199,7 @@ void loop() {
*/
if (IrReceiver.decode()) {
Serial.println();
-#if FLASHEND < 0x3FFF //
- // For less than 16k flash, only print a minimal summary of received data
+#if FLASHEND < 0x3FFF // For less than 16k flash, only print a minimal summary of received data
IrReceiver.printIRResultMinimal(&Serial);
#else
@@ -181,11 +212,13 @@ void loop() {
/*
* No overflow here.
* Stop receiver, generate a single beep, print short info and send usage and start receiver again
- *****************************************************************************************************/
-
+ */
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 defined(DEBUG_BUTTON_PIN)
+ && digitalRead(DEBUG_BUTTON_PIN) != LOW
+#endif
+ ) {
/*
* For SONY the tone prevents the detection of a repeat after the 15 ms SONY gap.
* In debug mode and for unknown protocols, we need the time for extended output.
@@ -198,14 +231,23 @@ void loop() {
/*
* Print info
*/
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+#if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+#endif
+ ) {
// We have 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);
}
- if (IrReceiver.decodedIRData.protocol != UNKNOWN) {
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN) {
+ auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs
+ Serial.print(F("Raw data received are 0x"));
+ Serial.println(tDecodedRawData);
+
+ } else {
/*
* The info output for a successful receive
*/
@@ -225,11 +267,16 @@ void loop() {
/*
* Finally check the received data and perform actions according to the received address and commands
*/
- if (IrReceiver.decodedIRData.address == 0) {
- if (IrReceiver.decodedIRData.command == 0x10) {
- // do something
- } else if (IrReceiver.decodedIRData.command == 0x11) {
- // do something else
+
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (IrReceiver.decodedIRData.address == 0) {
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ // do something else
+ }
}
}
@@ -251,28 +298,30 @@ void loop() {
}
+#if FLASHEND >= 0x3FFF // No tone() available when using ATTinyCore
/*
* Stop receiver, generate a single beep and start receiver again
*/
void generateTone() {
-#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
-# if defined(ESP32) // ESP32 uses another timer for tone()
+# 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(), maybe other platforms (not tested yet) too.
tone(TONE_PIN, 2200, 8);
-# else
- IrReceiver.stopTimer(); // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too.
+# else
+ IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
tone(TONE_PIN, 2200, 8);
delay(8);
- IrReceiver.restartTimer(8000); // Restart IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement.
+ IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
+# endif
# endif
-#endif
}
+#endif // FLASHEND >= 0x3FFF
void handleOverflow() {
Serial.println(F("Overflow detected"));
Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__));
// see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library
-#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
+#if !defined(ESP8266) && !defined(NRF5) && FLASHEND >= 0x3FFF // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
/*
* Stop timer, generate a double beep and start timer again
*/
@@ -286,7 +335,7 @@ void handleOverflow() {
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.
+ IrReceiver.restartTimer();
# endif
#endif
}
diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveDump/PinDefinitionsAndMore.h
+++ b/examples/ReceiveDump/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino
index 8f58e31ca..c0af4cb37 100644
--- a/examples/ReceiveDump/ReceiveDump.ino
+++ b/examples/ReceiveDump/ReceiveDump.ino
@@ -10,7 +10,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2024 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,22 +36,23 @@
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#if !defined(RAW_BUFFER_LENGTH)
-// For air condition remotes it requires 750. Default is 200.
+// For air condition remotes it may require up to 750. Default is 200.
# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF))
-#define RAW_BUFFER_LENGTH 750
+#define RAW_BUFFER_LENGTH 730 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000
# endif
#endif
/*
* MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
- * to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
+ * to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+ * 20 is taken as default if not otherwise specified / defined.
*
* You can change this value accordingly to the receiver module you use.
* The required value can be derived from the timings printed here.
* Keep in mind that the timings may change with the distance
* between sender and receiver as well as with the ambient light intensity.
*/
-#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@@ -65,13 +66,17 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200); // Status message will be sent to PC at 9600 baud
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
+
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -85,7 +90,14 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
+ Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
+
Serial.println();
Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!"));
Serial.println();
@@ -124,11 +136,14 @@ void loop() {
Serial.print(F("Result as internal 8bit ticks (50 us) array - compensated with MARK_EXCESS_MICROS="));
Serial.println(MARK_EXCESS_MICROS);
IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, false); // Output the results as uint8_t source code array of ticks
+ Serial.println(); // blank line between entries
Serial.print(F("Result as microseconds array - compensated with MARK_EXCESS_MICROS="));
Serial.println(MARK_EXCESS_MICROS);
IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros
+ Serial.println(); // blank line between entries
IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables
Serial.println(); // blank line between entries
+ Serial.println(); // blank line between entries
IrReceiver.compensateAndPrintIRResultAsPronto(&Serial);
diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
+++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
index 28f5c2524..3eb22c933 100644
--- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
+++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino
@@ -13,7 +13,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2024 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -90,6 +90,8 @@
#include
+//#define NO_LED_FEEDBACK_CODE // Saves 104 bytes program memory
+
// select only Samsung protocol for sending and receiving
#define DECODE_SAMSUNG
#define ADDRESS_OF_SAMSUNG_REMOTE 0x07 // The value you see as address in printIRResultShort()
@@ -104,8 +106,6 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -127,7 +127,11 @@ void setup() {
printActiveIRProtocols(&Serial);
Serial.println(F("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
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN)));
}
@@ -222,7 +226,7 @@ void sendSamsungSmartHubMacro(bool aDoSelect) {
delay(200);
#if !defined(ESP32)
- IrReceiver.restartTimer(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement.
+ IrReceiver.restartTimer(); // Restart IR timer.
#endif
Serial.println(F("Wait for \"not supported\" to disappear"));
diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
index c0efd284f..ab732bcd0 100644
--- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
+++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino
@@ -48,13 +48,16 @@ void measureTimingISR(void);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
- Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
+ Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__));
@@ -70,7 +73,11 @@ void setup() {
EIMSK |= _BV(INT1); // enable interrupt on next change
# endif
#else
+# if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
+ attachInterrupt(IR_RECEIVE_PIN, measureTimingISR, CHANGE);
+# else
attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE);
+# endif
#endif
Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN)));
Serial.println();
diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendAndReceive/PinDefinitionsAndMore.h
+++ b/examples/SendAndReceive/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino
index 9e99353dc..eec023f16 100644
--- a/examples/SendAndReceive/SendAndReceive.ino
+++ b/examples/SendAndReceive/SendAndReceive.ino
@@ -38,10 +38,12 @@
//#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 8000. Activate it for some LG air conditioner protocols
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // saves 318 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 44 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 36 bytes program memory
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
@@ -53,8 +55,6 @@
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -69,7 +69,11 @@ void setup() {
Serial.print(F("Ready to receive IR signals of protocols: "));
printActiveIRProtocols(&Serial);
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
@@ -91,8 +95,13 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
}
diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
+++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
index a7eafb3d6..eb2fcdd02 100644
--- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
+++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino
@@ -37,6 +37,8 @@
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
+//#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory
+
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include
@@ -110,8 +112,6 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -121,11 +121,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 -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
#else
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
+ IrSender.begin(tSendPin); // Specify send pin and enable feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendDemo/PinDefinitionsAndMore.h
+++ b/examples/SendDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino
index c644f3e4c..208b1adb3 100644
--- a/examples/SendDemo/SendDemo.ino
+++ b/examples/SendDemo/SendDemo.ino
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,34 +37,58 @@
#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(.
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
+//#define IR_USE_AVR_TIMER1
//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
+//#define USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin.
+//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-//#define 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_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal.
+//#define NO_LED_FEEDBACK_CODE // Saves 322 bytes program memory
+#if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85
+#define NO_LED_FEEDBACK_CODE
+#endif
//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
#include
#define DELAY_AFTER_SEND 2000
#define DELAY_AFTER_LOOP 5000
+#if __INT_WIDTH__ < 32
+IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
+/*
+ * Alternative definition of tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010}
+ * But be aware, that this requires a cast when using tRawDataPGM as parameter.
+ * Like sendPulseDistanceWidthFromPGMArray_P(..., (IRRawDataType*) &tRawDataPGM[0], ...);
+ */
+//uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/
+//0x10, 0xA0, 0x0, 0x0, /*0xA010*/};
+#endif
+
+const uint16_t rawIRTimingsNEC[] PROGMEM
+= { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560,
+ 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560,
+ 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560,
+ 560/*0000 0x00*/, 560, 1690, 560, 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690,
+ 560, 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
+
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
+
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN -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
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
# if defined(IR_SEND_PIN_STRING)
Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
@@ -73,7 +97,7 @@ void setup() {
#else
// 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
+ IrSender.begin(tSendPin); // Specify send pin and use feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
@@ -93,16 +117,27 @@ void setup() {
Serial.print(IrSender.periodTimeMicros);
Serial.println(F(" us"));
#endif
+
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE) && !defined(NO_LED_SEND_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
}
/*
* Set up the data to be sent.
* For most protocols, the data is build up with a constant 8 (or 16 byte) address
* and a variable 8 bit command.
- * There are exceptions like Sony and Denon, which have 5 bit address.
+ * There are exceptions like Sony, Denon or Marantz, which have 5 bit address.
+ * Furthermore, the extended protocol from Marantz has a 6 bit command extension.
*/
uint16_t sAddress = 0x0102;
uint8_t sCommand = 0x34;
+uint8_t sCommandExtension = 0x0B; // Only used for Marantz extended protocol
uint16_t s16BitCommand = 0x5634;
uint8_t sRepeats = 0;
@@ -137,11 +172,22 @@ void loop() {
delay(DELAY_AFTER_SEND);
if (sRepeats == 0) {
-#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.
+#if FLASHEND >= 0x3FFF && ((!defined(RAMEND) && !defined(RAMSIZE)) || (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
*/
- Serial.println(F("Sending NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
+
+ /*
+ * Test send usage for UNKNOWN protocol
+ */
+ const uint16_t rawIRTimings[] = { 9000, 4500/*Start bit*/, 500, 1000, 1000, 500, 500, 2000, 2000, 500, 500, 3000, 3000, 500,
+ 500, 250, 250, 500 };
+ Serial.println(F("Send arbitrary raw data with exact timing (16 bit array format) with sendRaw()"));
+ Serial.flush();
+ IrSender.sendRaw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), NEC_KHZ, 80, 1); // Note the approach used to automatically calculate the size of the array.
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()"));
Serial.flush();
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
"0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */
@@ -152,18 +198,13 @@ void loop() {
delay(DELAY_AFTER_SEND);
/*
- * !!! The next data occupies 136 bytes RAM !!!
+ * Test sending NEC protocol using sendRaw_P
*/
Serial.println(
- F("Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)"));
+ F(
+ "Send NEC data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format) with sendRaw_P()"));
Serial.flush();
- const uint16_t irSignal[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
- 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690,
- 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560,
- 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560,
- 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560,
- 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
- IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
+ IrSender.sendRaw_P(rawIRTimingsNEC, sizeof(rawIRTimingsNEC) / sizeof(rawIRTimingsNEC[0]), NEC_KHZ, 110, 1); // Note the approach used to automatically calculate the size of the array.
delay(DELAY_AFTER_SEND);
/*
@@ -185,86 +226,99 @@ void loop() {
Serial.flush();
IrSender.sendNECMSB(0x40802CD3, 32, false);
delay(DELAY_AFTER_SEND);
-#endif
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432"));
Serial.flush();
-#if __INT_WIDTH__ < 32
- IRRawDataType tRawData[] = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
-#else
- IrSender.sendPulseDistanceWidth(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
-#endif
+# if __INT_WIDTH__ < 32
+ IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+# else
+ IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+# endif
delay(DELAY_AFTER_SEND);
/*
* Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first
*/
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400"));
Serial.println(F(" LSB first"));
Serial.flush();
-#if __INT_WIDTH__ < 32
- IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
+# if __INT_WIDTH__ < 32
+ IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48,
PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
-#else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
- 0, NO_REPEATS);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
// The same with MSB first. Use bit reversed raw data of LSB first part
Serial.println(F(" MSB first"));
-#if __INT_WIDTH__ < 32
+ IRRawDataType tRawData[4];
+# if __INT_WIDTH__ < 32
tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first
tRawData[1] = 0x805;
IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48,
PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
-#else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST,
- 0, NO_REPEATS);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600"));
Serial.flush();
-# if __INT_WIDTH__ < 32
+# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
tRawData[1] = 0xAFEDCBA9;
tRawData[2] = 0x5A;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
NO_REPEATS);
-# else
- IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
-# endif
+# else
+ tRawData[0] = 0xAFEDCBA987654321;
+ tRawData[1] = 0x5A; // LSB of tRawData[0] is sent first
+ IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
+# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
-#if __INT_WIDTH__ < 32
+# if __INT_WIDTH__ < 32
IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52,
PROTOCOL_IS_LSB_FIRST, 0, 0);
-#else
- IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST,
- 0, 0);
-#endif
+# else
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first"));
+ Serial.println(
+ F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600"));
+ Serial.flush();
+# if __INT_WIDTH__ < 32
+ tRawData[2] = ~tRawData[0];
+ tRawData[3] = ~tRawData[1];
+ IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# else
+ IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0);
+# endif
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
IrSender.sendPulseDistanceWidth(38, 6000, 500, 500, 1500, 1500, 500, sCommand, 7, PROTOCOL_IS_LSB_FIRST, 0, 0);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Sony12 as PulseWidth LSB first"));
+ Serial.println(F("Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600"));
Serial.flush();
uint32_t tData = (uint32_t) sAddress << 7 | (sCommand & 0x7F);
IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, tData, SIRCS_12_PROTOCOL, PROTOCOL_IS_LSB_FIRST, 0, 0);
delay(DELAY_AFTER_SEND);
+#endif // FLASHEND >= 0x3FFF ...
- Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first"));
+ Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
@@ -346,12 +400,27 @@ void loop() {
IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
delay(DELAY_AFTER_SEND);
+ Serial.println(F("Send Marantz variant of RC5x with 6 command bits and additional command extension"));
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand, sCommandExtension, sRepeats);
+ delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send Marantz variant of RC5x with 7 command bits and additional command extension"));
+ Serial.flush();
+ IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sCommandExtension, sRepeats);
+ delay(DELAY_AFTER_SEND);
+
Serial.println(F("Send RC6"));
Serial.flush();
IrSender.sendRC6(sAddress, sCommand, sRepeats, true);
delay(DELAY_AFTER_SEND);
-#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.
+ Serial.println(F("Send RC6A with 14 bit 0x2711 as extra"));
+ Serial.flush();
+ IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true);
+ delay(DELAY_AFTER_SEND);
+
+#if FLASHEND >= 0x3FFF && ((!defined(RAMEND) && !defined(RAMSIZE)) || (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.
Serial.println(F("Send MagiQuest"));
Serial.flush();
@@ -383,7 +452,7 @@ void loop() {
IrSender.write(&IRSendData, sRepeats);
delay(DELAY_AFTER_SEND);
- IRSendData.command = s16BitCommand; // LG support more than 8 bit command
+ IRSendData.command = s16BitCommand; // LG support more than 8 bit command
IRSendData.protocol = SAMSUNG;
Serial.print(F("Send "));
diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
+++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
index 90511f282..7dc2ca86f 100644
--- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
+++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino
@@ -32,6 +32,8 @@
*/
#include
+//#define NO_LED_FEEDBACK_CODE // Saves 276 bytes program memory
+
/*
* LG2 has different header timing and a shorter bit time
* Known LG remote controls, which uses LG2 protocol are:
@@ -46,6 +48,8 @@
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
+//#define NO_LED_FEEDBACK_CODE // Saves 214 bytes program memory
+
#define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver.
//#define DEBUG // Activate this for more output from the LG-AC driver.
@@ -67,21 +71,21 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
-delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
+
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
/*
- * The IR library setup. That's all!
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
*/
- IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
Serial.println();
MyLG_Aircondition.setType(LG_IS_WALL_TYPE);
diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendProntoDemo/PinDefinitionsAndMore.h
+++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino
index d4893f033..f08a7035b 100644
--- a/examples/SendProntoDemo/SendProntoDemo.ino
+++ b/examples/SendProntoDemo/SendProntoDemo.ino
@@ -36,6 +36,8 @@
#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required.
#endif
+//#define NO_LED_FEEDBACK_CODE // Saves 266 bytes program memory
+
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include
@@ -59,14 +61,21 @@ IRsend irsend;
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
+
+#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
+ || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
+ delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
- IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
}
void loop() {
diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SendRawDemo/PinDefinitionsAndMore.h
+++ b/examples/SendRawDemo/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino
index 8e1847517..02f28f4ca 100644
--- a/examples/SendRawDemo/SendRawDemo.ino
+++ b/examples/SendRawDemo/SendRawDemo.ino
@@ -42,7 +42,7 @@
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-//#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory
+//#define NO_LED_FEEDBACK_CODE // Saves 220 bytes program memory
//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
@@ -52,8 +52,6 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
@@ -63,7 +61,11 @@ 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 -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
}
/*
diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SimpleReceiver/PinDefinitionsAndMore.h
+++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino
index 36d79a6fd..84b040376 100644
--- a/examples/SimpleReceiver/SimpleReceiver.ino
+++ b/examples/SimpleReceiver/SimpleReceiver.ino
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,7 +43,7 @@
//#define DECODE_KASEIKYO
//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
//#define DECODE_LG
-#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line.
+//#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
@@ -62,7 +62,8 @@
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it requires 750. Default is 200.
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Saves 110 bytes program memory.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
/*
* This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
@@ -72,8 +73,6 @@
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -104,9 +103,11 @@ void loop() {
Serial.println(F("Received noise or an unknown (or not yet enabled) protocol"));
// 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);
}
@@ -115,10 +116,16 @@ void loop() {
/*
* Finally, check the received data and perform actions according to the received command
*/
- if (IrReceiver.decodedIRData.command == 0x10) {
- // do something
- } else if (IrReceiver.decodedIRData.command == 0x11) {
- // do something else
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ Serial.println(F("Received command 0x10."));
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ Serial.println(F("Received command 0x11."));
+ // do something else
+ }
}
}
}
diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h
+++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino
index 17d84e08c..91819446b 100644
--- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino
+++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino
@@ -32,12 +32,18 @@
#include
+#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
+
/*
* Specify which protocol(s) should be used for decoding.
* This must be done before the #include
*/
#define DECODE_HASH // special decoder for all protocols
+#if !defined(RAW_BUFFER_LENGTH)
+# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF))
#define RAW_BUFFER_LENGTH 1000 // Especially useful for unknown and probably long protocols
+# endif
+#endif
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
/*
@@ -48,8 +54,6 @@
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -68,23 +72,30 @@ void loop() {
if (IrReceiver.available()) {
IrReceiver.initDecodedIRData(); // is required, if we do not call decode();
IrReceiver.decodeHash();
+ IrReceiver.resume(); // Early enable receiving of the next IR frame
/*
- * Print a summary of received data
+ * Print a summary and then timing of received data
*/
- // We have an unknown protocol here, print extended info
+ IrReceiver.printIRResultShort(&Serial);
IrReceiver.printIRResultRawFormatted(&Serial, true);
- IrReceiver.resume(); // Early enable receiving of the next IR frame
- IrReceiver.printIRResultShort(&Serial);
Serial.println();
/*
* Finally, check the received data and perform actions according to the received command
*/
- if (IrReceiver.decodedIRData.decodedRawData == 0x4F7BE2FB) {
- // do something
- } else if (IrReceiver.decodedIRData.decodedRawData == 0x97483BFB) {
- // do something else
+ auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs
+ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) {
+ Serial.println(F("Repeat received. Here you can repeat the same action as before."));
+ } else {
+ Serial.print(F("Raw data received are 0x"));
+ Serial.println(tDecodedRawData);
+
+ if (IrReceiver.decodedIRData.command == 0x10) {
+ // do something
+ } else if (IrReceiver.decodedIRData.command == 0x11) {
+ // do something else
+ }
}
}
}
diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h
+++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino
index a857203f2..5489dbc81 100644
--- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino
+++ b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino
@@ -59,7 +59,7 @@
//#define DEBUG // Activate this for lots of lovely debug output from the decoders.
-//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it requires 750. Default is 200.
+//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it may require up to 750. Default is 200.
#include
@@ -77,8 +77,6 @@ void ReceiveCompleteCallbackHandler();
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/SimpleSender/PinDefinitionsAndMore.h
+++ b/examples/SimpleSender/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino
index d73b37485..91797630e 100644
--- a/examples/SimpleSender/SimpleSender.ino
+++ b/examples/SimpleSender/SimpleSender.ino
@@ -3,8 +3,9 @@
*
* Demonstrates sending IR codes in standard format with address and command
* An extended example for sending can be found as SendDemo.
+ * Sending IR codes using several pins for sending is implements in the MultipleSendPins example.
*
- * Copyright (C) 2020-2022 Armin Joachimsmeyer
+ * Copyright (C) 2020-2025 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
@@ -18,6 +19,7 @@
#endif
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
+//#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory
/*
* This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures
@@ -29,8 +31,6 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -38,10 +38,10 @@ void setup() {
Serial.println(IR_SEND_PIN);
/*
- * The IR library setup. That's all!
+ * No IR library setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
*/
- IrSender.begin(); // Start with IR_SEND_PIN -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
}
/*
diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/TinyReceiver/PinDefinitionsAndMore.h
+++ b/examples/TinyReceiver/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino
index bad39fea2..b31b4657f 100644
--- a/examples/TinyReceiver/TinyReceiver.ino
+++ b/examples/TinyReceiver/TinyReceiver.ino
@@ -67,7 +67,7 @@
* 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.
+//#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
#include "TinyIRReceiver.hpp" // include the code
@@ -81,13 +81,17 @@
void setup() {
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
+
// Just to know which program is running on my Arduino
#if defined(ESP8266) || defined(ESP32)
Serial.println();
@@ -106,14 +110,15 @@ void setup() {
}
void loop() {
- if (TinyIRReceiverData.justWritten) {
- TinyIRReceiverData.justWritten = false;
+ if (TinyReceiverDecode()) {
+
#if !defined(USE_FAST_PROTOCOL)
// We have no address at FAST protocol
Serial.print(F("Address=0x"));
Serial.print(TinyIRReceiverData.Address, HEX);
Serial.print(' ');
#endif
+
Serial.print(F("Command=0x"));
Serial.print(TinyIRReceiverData.Command, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
@@ -121,15 +126,21 @@ void loop() {
}
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
Serial.print(F(" Parity failed"));
+
#if !defined(USE_EXTENDED_NEC_PROTOCOL) && !defined(USE_ONKYO_PROTOCOL)
Serial.print(F(", try USE_EXTENDED_NEC_PROTOCOL or USE_ONKYO_PROTOCOL"));
#endif
+
}
Serial.println();
}
/*
* Put your code here
*/
+
+ /*
+ * No resume() required :-)
+ */
}
/*
diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/TinySender/PinDefinitionsAndMore.h
+++ b/examples/TinySender/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino
index 7a1fb3432..4af49883b 100644
--- a/examples/TinySender/TinySender.ino
+++ b/examples/TinySender/TinySender.ino
@@ -54,8 +54,6 @@ void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h
index 37d57d93a..907e2a641 100644
--- a/examples/UnitTest/PinDefinitionsAndMore.h
+++ b/examples/UnitTest/PinDefinitionsAndMore.h
@@ -35,14 +35,15 @@
* ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core
* ATtiny84 |PB2 |PA4 |PA3 ATTinyCore
* ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore
- * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore
+ * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore
* ATtiny1604 2 3|PA5 %
* ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore
* ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore
- * SAMD21 3 4 5
+ * MKR* 1 3 4
+ * SAMD 2 3 4
* ESP8266 14|D5 12|D6 %
* ESP32 15 4 27
- * ESP32-C3 6 7 10
+ * ESP32-C3 2 3 4
* BluePill PA6 PA7 PA3
* APOLLO3 11 12 5
* RP2040 3|GPIO15 4|GPIO16 5|GPIO17
@@ -50,7 +51,7 @@
//#define _IR_MEASURE_TIMING // For debugging purposes.
#if defined(__AVR__)
-#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore.
+#if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore.
#define IR_RECEIVE_PIN PIN_PB0
#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
@@ -60,28 +61,30 @@
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
-# if defined(ARDUINO_AVR_DIGISPARKPRO)
+# if defined(ARDUINO_AVR_DIGISPARKPRO)
// For use with Digispark original core
#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9
//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5
#define _IR_TIMING_TEST_PIN 10 // PA4
-# else
+# elif !defined(PIN_PA3)
+#error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h.
+# else
// For use with ATTinyCore
#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards
#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8
#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5
-# endif
+# endif
-# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore
+# elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
#define IR_RECEIVE_PIN PIN_PB2 // INT0
#define IR_SEND_PIN PIN_PA4
#define TONE_PIN PIN_PA3
#define _IR_TIMING_TEST_PIN PIN_PA5
-# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore.
+# elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore.
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory.
// Pin 6 is TX, pin 7 is RX
#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1
@@ -89,32 +92,32 @@
#define TONE_PIN PIN_PB1 // 9
#define _IR_TIMING_TEST_PIN PIN_PB0 // 8
-# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore
+# elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore
// Tiny Core Dev board
// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - 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
+#define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
+#define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32
+#define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32
+#define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET
#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output
#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32
-# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 14
-#define IR_SEND_PIN PIN_PA1 // 16
+#define IR_SEND_PIN PIN_PA3 // 16
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output
#define LED_BUILTIN PIN_PB5 // 4
-# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore
#define IR_RECEIVE_PIN PIN_PA1 // 8
#define IR_SEND_PIN PIN_PA3 // 10
#define TONE_PIN PIN_PA5 // 1
#define APPLICATION_PIN PIN_PA4 // 0
-# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore
+# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA6) // 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
@@ -172,22 +175,32 @@
#define tone(...) void() // tone() inhibits receive timer
#define noTone(a) void()
-#define TONE_PIN 42 // Dummy for examples using it
+#define TONE_PIN 42 // Dummy for examples using it#
+
+#elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI)
+#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW
+#define IR_RECEIVE_PIN 2
+#define IR_SEND_PIN 3
+#define TONE_PIN 4
+#define APPLICATION_PIN 10
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#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
+#define TONE_PIN 9
+#define APPLICATION_PIN 10
#elif defined(ESP32)
#include
// tone() is included in ESP32 core since 2.0.2
-#if !defined(ESP_ARDUINO_VERSION_VAL)
-#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678
-#endif
+# if !defined(ESP_ARDUINO_VERSION)
+#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
+# endif
+# if !defined(ESP_ARDUINO_VERSION_VAL)
+#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
+# endif
#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
@@ -210,7 +223,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1
#define APPLICATION_PIN 16 // RX2 pin
-#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill
+#elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill
// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define IR_RECEIVE_PIN PA6
#define IR_RECEIVE_PIN_STRING "PA6"
@@ -252,7 +265,7 @@ void noTone(uint8_t aPinNumber){
#undef LED_BUILTIN
#define LED_BUILTIN 6
-#elif defined(PARTICLE) // !!!UNTESTED!!!
+#elif defined(PARTICLE) && defined(A4) // !!!UNTESTED!!!
#define IR_RECEIVE_PIN A4
#define IR_SEND_PIN A5 // Particle supports multiple pins
@@ -278,7 +291,11 @@ void noTone(uint8_t aPinNumber){
#define _IR_TIMING_TEST_PIN 7
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
+# if defined(USE_ARDUINO_MKR_PIN_LAYOUT)
+#define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/
+# else
#define IR_RECEIVE_PIN 2
+# endif
#define IR_SEND_PIN 3
#define TONE_PIN 4
#define APPLICATION_PIN 5
@@ -311,7 +328,7 @@ void noTone(uint8_t aPinNumber){
#define TONE_PIN 42 // Dummy for examples using it
#else
-#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
+#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IR_RECEIVE_PIN 2
#define IR_SEND_PIN 3
diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino
index cce8f42e4..d9049d2da 100644
--- a/examples/UnitTest/UnitTest.ino
+++ b/examples/UnitTest/UnitTest.ino
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2024 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -46,13 +46,23 @@
//#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory.
//#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used
+//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 24 bytes program memory.
+//#define USE_STRICT_DECODER // Check for additional required characteristics of protocol timing. Requires 300 additional bytes program memory.
+//#define USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin.
+//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM.
//#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition
-#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory
-// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
+//#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal.
+#define NO_LED_FEEDBACK_CODE // Saves 270 bytes program memory
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 176 bytes program memory
+//#define NO_LED_SEND_FEEDBACK_CODE // Saves 38 bytes program memory
+
//#define USE_MSB_DECODING_FOR_DISTANCE_DECODER
-// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142.
-//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity.
+
+// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,
+// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135.
+// 20 is taken as default if not otherwise specified / defined.
+//#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity.
//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols.
@@ -79,32 +89,41 @@
#define DECODE_SONY
#define DECODE_SAMSUNG
#define DECODE_LG
+#define DECODE_LEGO_PF // LEGO is skipped, since it is difficult to receive because of its short marks and spaces
+#endif
#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:100:2!!!
#if defined(DECODE_BEO)
#define RECORD_GAP_MICROS 16000 // Force to get the complete frame including the 3. space of 15 ms in the receive buffer
+#define SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING // We know, what we do here :-)
#define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz here (instead of 455 kHz).
#endif
#define DECODE_BOSEWAVE
-//#define DECODE_LEGO_PF
#define DECODE_MAGIQUEST
-//#define DECODE_WHYNTER
#define DECODE_FAST
-#endif
+
+//#define DECODE_WHYNTER
//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below
+
+#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints errors which prevents data to be decoded as distance width data
#include
-#if defined(APPLICATION_PIN)
+#if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN)
#define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data
#else
#define DEBUG_BUTTON_PIN 6
#endif
+#if defined(ESP32) && defined(DEBUG_BUTTON_PIN)
+# if !digitalPinIsValid(DEBUG_BUTTON_PIN)
+#undef DEBUG_BUTTON_PIN // DEBUG_BUTTON_PIN number is not valid, so delete definition to disable further usage
+# endif
+#endif
-#define DELAY_AFTER_SEND 1000
-#define DELAY_AFTER_LOOP 5000
+#define DELAY_AFTER_SEND 700
+#define DELAY_AFTER_LOOP 3000
#if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
#error Unit test cannot run if SEND_PWM_BY_TIMER is enabled i.e. receive timer us also used by send
@@ -116,16 +135,35 @@
volatile bool sDataJustReceived = false;
void ReceiveCompleteCallbackHandler();
+#if __INT_WIDTH__ < 32
+//IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first
+uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/
+0x10, 0xA0, 0x0, 0x0, /*0xA010*/}; // Define tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010}
+#endif
+
+// if this definition is contained in a function, the address, the compiler uses is wrong :-(
+const uint16_t rawIRTimingsNEC[] PROGMEM
+= { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560,
+ 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560,
+ 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560,
+ 560/*0000 0x00*/, 560, 1690, 560, 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690,
+ 560, 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
+
void setup() {
+#if defined(DEBUG_BUTTON_PIN)
pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP);
+#endif
Serial.begin(115200);
- while (!Serial)
- ; // Wait for Serial to become available. Is optimized away for some cores.
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
|| defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
- delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
+ // Wait until Serial Monitor is attached.
+ // Required for boards using USB code for Serial like Leonardo.
+ // Is void for USB Serial implementations using external chips e.g. a CH340.
+ while (!Serial)
+ ;
+ // !!! Program will not proceed if no Serial Monitor is attached !!!
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
@@ -142,11 +180,23 @@ void setup() {
Serial.println(F("at pin " STR(IR_RECEIVE_PIN)));
#endif
+#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ Serial.print(F("Active low "));
+# endif
+ Serial.print(F("FeedbackLED at pin "));
+ Serial.println(LED_BUILTIN); // Works also for ESP32: static const uint8_t LED_BUILTIN = 8; #define LED_BUILTIN LED_BUILTIN
+#endif
+
Serial.println(F("Use ReceiveCompleteCallback"));
Serial.println(F("Receive buffer length is " STR(RAW_BUFFER_LENGTH)));
#if defined(IR_SEND_PIN)
- IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin
+ /*
+ * No IR send setup required :-)
+ * Default is to use IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin
+ * and use feedback LED at default feedback LED pin if not disabled by #define NO_LED_SEND_FEEDBACK_CODE
+ */
# if defined(IR_SEND_PIN_STRING)
Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING));
# else
@@ -155,7 +205,7 @@ void setup() {
#else
// 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
+ IrSender.begin(tSendPin);// Specify send pin and use feedback LED at default feedback LED pin
// You can change send pin later with IrSender.setSendPin();
Serial.print(F("Send IR signals at pin "));
@@ -163,13 +213,11 @@ void setup() {
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
+# if defined(DEBUG_BUTTON_PIN)
Serial.print(F("If you connect debug pin "));
-# if defined(APPLICATION_PIN_STRING)
- Serial.print(APPLICATION_PIN_STRING);
-# else
Serial.print(DEBUG_BUTTON_PIN);
-# endif
Serial.println(F(" to ground, raw data is always printed"));
+# endif
// For esp32 we use PWM generation by ledcWrite() for each pin.
# if !defined(SEND_PWM_BY_TIMER)
@@ -189,8 +237,13 @@ void setup() {
// infos for receive
Serial.print(RECORD_GAP_MICROS);
Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed"));
+
+# if defined(USE_THRESHOLD_DECODER)
+ Serial.println(F("Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0"));
+# else
Serial.print(MARK_EXCESS_MICROS);
Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding"));
+# endif
#endif
delay(DELAY_AFTER_SEND);
@@ -211,11 +264,16 @@ void checkReceivedRawData(IRRawDataType aRawData) {
IrReceiver.printIRResultMinimal(&Serial);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
- // We have an unknown protocol, print more info
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
+ // We have an unknown protocol or debug button is held low, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
-#endif
+#endif // FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
+
if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) {
if (IrReceiver.decodedIRData.decodedRawData != aRawData) {
Serial.print(F("ERROR: Received data=0x"));
@@ -231,6 +289,8 @@ void checkReceivedRawData(IRRawDataType aRawData) {
PrintULL::print(&Serial, aRawData, HEX);
#endif
Serial.println();
+ IrReceiver.printIRResultAsCArray(&Serial, false, false); // To be able to easily compare received with sent data
+ Serial.println();
}
}
IrReceiver.resume();
@@ -256,8 +316,12 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
IrReceiver.printIRResultMinimal(&Serial);
#endif
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
- // We have an unknown protocol, print more info
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
+ // We have an unknown protocol or debug button is held low, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
#endif
@@ -273,6 +337,7 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize)
# endif
Serial.print(F(" != sent data=0x"));
Serial.println(*aRawDataArrayPointer, HEX);
+ IrReceiver.printIRResultAsCArray(&Serial, false, false);
}
aRawDataArrayPointer++;
}
@@ -321,7 +386,11 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
}
#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604
- if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) {
+ if (IrReceiver.decodedIRData.protocol == UNKNOWN
+# if defined(DEBUG_BUTTON_PIN)
+ || digitalRead(DEBUG_BUTTON_PIN) == LOW
+# endif
+ ) {
// We have an unknown protocol, print more info
IrReceiver.printIRResultRawFormatted(&Serial, true);
}
@@ -367,6 +436,11 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) {
uint16_t sAddress = 0xFFF1;
uint8_t sCommand = 0x76;
uint16_t s16BitCommand = 0x9876;
+/*
+ * Repeats cannot be automatically checked, because just the first frame is stored in receive buffer and all repeat frames are skipped.
+ * We cannot issue a resume() before sending of an repeat, because we use the blocking send*() functions.
+ * But an independent receiver could check it
+ */
uint8_t sRepeats = 0;
void loop() {
@@ -378,24 +452,35 @@ void loop() {
Serial.print(sAddress, HEX);
Serial.print(F(" command=0x"));
Serial.print(sCommand, HEX);
+ if (sRepeats > 0) {
+ Serial.print(F(" repeats="));
+ Serial.print(sRepeats);
+ }
+
Serial.println();
Serial.println();
+#if defined(DECODE_NEC)
+ /*
+ * Sending complete NEC frames as repeats to force decoding as NEC2 are tested here
+ */
Serial.print(F("Send NEC with 8 bit address"));
if (sRepeats > 0) {
Serial.print(F(" and complete NEC frames as repeats to force decoding as NEC2"));
}
Serial.println();
Serial.flush();
- IrSender.sendNEC(sAddress & 0xFF, sCommand, 0);
+ IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); // sending first frame -> decodes as NEC
checkReceive(sAddress & 0xFF, sCommand);
for (int8_t i = 0; i < sRepeats; i++) {
+# if defined(DEBUG_BUTTON_PIN)
if (digitalRead(DEBUG_BUTTON_PIN) != LOW) {
- // if debug is enabled, printing time (50 ms) is too high anyway
- delayMicroseconds(NEC_REPEAT_DISTANCE - 200); // 200 is just a guess
+ // If debug is enabled, printing time (50 ms) is sufficient as delay
+ delayMicroseconds(NEC_REPEAT_DISTANCE - 20000); // 20000 is just a guess
}
- IrSender.sendNEC(sAddress & 0xFF, sCommand, 0);
+# endif
+ IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); // sending repeat frames -> decodes as NEC2
checkReceive(sAddress & 0xFF, sCommand);
}
@@ -403,24 +488,40 @@ void loop() {
Serial.println(F("Send NEC with 16 bit address"));
Serial.flush();
- IrSender.sendNEC(sAddress, sCommand, 0);
+ IrSender.sendNEC(sAddress, sCommand, sRepeats); // no repeats
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send NEC2 with 16 bit address"));
Serial.flush();
- IrSender.sendNEC2(sAddress, sCommand, 0);
+ IrSender.sendNEC2(sAddress, sCommand, sRepeats);
checkReceive(sAddress, sCommand);
delay(DELAY_AFTER_SEND);
+#endif // defined(DECODE_NEC)
-#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc.
+#if FLASHEND >= 0x7FFF && ((!defined(RAMEND) && !defined(RAMSIZE)) || (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.
+ if (sCommand == 0x76) {
+ /*
+ * Do this only once at the first loop
+ */
+ IRRawDataType tRawData[4];
+
+ /*
+ * Test send usage for UNKNOWN protocol
+ */
+ const uint16_t rawIRTimings[] = { 9000, 4500/*Start bit*/, 500, 1000, 1000, 500, 500, 2000, 2000, 500, 500, 3000, 3000, 500,
+ 500, 250, 250, 500 };
+ Serial.println(F("Send arbitrary raw data with 1 repeat and exact timing (16 bit array format) with sendRaw()"));
+ Serial.flush();
+ IrSender.sendRaw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), NEC_KHZ, 80, 1); // Note the approach used to automatically calculate the size of the array.
+ checkReceive(0xFB04 & 0xFF, 0x08);
+ delay(DELAY_AFTER_SEND);
- if (sAddress == 0xFFF1) {
-# 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.
+# if defined(DECODE_NEC)
/*
* Send constant values only once in this demo
*/
- Serial.println(F("Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats"));
+ Serial.println(F("Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()"));
Serial.flush();
// This is copied to stack/ram internally
IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */
@@ -432,16 +533,14 @@ void loop() {
checkReceive(0x80, 0x45);
delay(DELAY_AFTER_SEND);
+ /*
+ * Test sending NEC protocol using sendRaw_P
+ */
Serial.println(
- F("Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)"));
+ F(
+ "Send NEC data with 8 bit address=0xFB04, command 0x08, 1 repeat and exact timing (16 bit array format) with sendRaw_P()"));
Serial.flush();
- const uint16_t irSignal[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560,
- 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690,
- 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560,
- 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560,
- 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560,
- 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing
- IrSender.sendRaw(irSignal, sizeof(irSignal) / sizeof(irSignal[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array.
+ IrSender.sendRaw_P(rawIRTimingsNEC, sizeof(rawIRTimingsNEC) / sizeof(rawIRTimingsNEC[0]), NEC_KHZ, 110, 1); // Note the approach used to automatically calculate the size of the array.
checkReceive(0xFB04 & 0xFF, 0x08);
delay(DELAY_AFTER_SEND);
@@ -466,17 +565,16 @@ void loop() {
IrSender.sendNECMSB(0x40802CD3, 32, false);
checkReceive(0x0102, 0x34);
delay(DELAY_AFTER_SEND);
-# endif
+# endif // defined(DECODE_NEC)
# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432"));
Serial.flush();
# if __INT_WIDTH__ < 32
- IRRawDataType tRawData[4] = { 0xB02002, 0xA010, 0x0, 0x0 }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+ IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
+ IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant
checkReceivedRawData(0xA010B02002);
# endif
delay(DELAY_AFTER_SEND);
@@ -484,16 +582,16 @@ void loop() {
/*
* Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first
*/
- Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance"));
+ Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400"));
Serial.println(F("-LSB first"));
Serial.flush();
# if __INT_WIDTH__ < 32
- IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST, 0,
- NO_REPEATS);
+ IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48,
+ PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST,
- 0, NO_REPEATS);
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedRawData(0xA010B02002);
# endif
delay(DELAY_AFTER_SEND);
@@ -507,7 +605,8 @@ void loop() {
NO_REPEATS);
checkReceive(0x0B, 0x10);
# else
- IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
+ IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedRawData(0x40040D000805);
# endif
@@ -516,13 +615,13 @@ void loop() {
# if defined(DECODE_DISTANCE_WIDTH)
# if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- Serial.println(F("Send 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first"));
+ Serial.println(F("Send 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first 1=550|1700, 0=550|600"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x43D8613C; // MSB of tRawData[0] is sent first
tRawData[1] = 0x3BC3B;
IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, 0,
- NO_REPEATS);
+ NO_REPEATS);
checkReceivedArray(tRawData, 2);
# else
IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS);
@@ -530,7 +629,7 @@ void loop() {
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first"));
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first 1=600|300, 0=300|600"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
# if __INT_WIDTH__ < 32
@@ -541,7 +640,7 @@ void loop() {
checkReceivedRawData(0x123456789ABC);
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first"));
+ Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first 1=600|300, 0=300|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does not require a stop bit
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x43D8613C, 32, PROTOCOL_IS_MSB_FIRST, 0, 0);
@@ -549,7 +648,7 @@ void loop() {
delay(DELAY_AFTER_SEND);
# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first
@@ -559,13 +658,15 @@ void loop() {
NO_REPEATS);
checkReceivedArray(tRawData, 3);
# else
- IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first
- IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS);
+ tRawData[0] = 0xAFEDCBA987654321;
+ tRawData[1] = 0x5A; // LSB of tRawData[0] is sent first
+ IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4450, 550, 1700, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, 0,
+ NO_REPEATS);
checkReceivedArray(tRawData, 2);
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first"));
+ Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
# if __INT_WIDTH__ < 32
@@ -578,7 +679,8 @@ void loop() {
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data"));
+ Serial.println(
+ F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600"));
Serial.flush();
# if __INT_WIDTH__ < 32
tRawData[2] = ~tRawData[0];
@@ -591,100 +693,123 @@ void loop() {
# endif
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first"));
+ Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500"));
Serial.flush();
// Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission
IrSender.sendPulseDistanceWidth(38, 6000, 500, 500, 1500, 1500, 500, sCommand, 7, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Sony12 as PulseWidth LSB first"));
+ Serial.println(F("Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275"));
+ Serial.flush();
+ IrSender.sendPulseDistanceWidth_P(&VeluxProtocolConstants, 0x654321, VELUX_BITS, 0);
+ /*
+ * We send 24 bit MSB first so bitreverse32Bit() >> 8
+ * We send without header, so >> 1.
+ * We send as pulse width so we must invert result, which is decoded as pulse distance
+ */
+ checkReceivedRawData((~(((bitreverse32Bit(0x654321)) >> 8) >> 1)) & 0x7FFFFF);
+#if false
+ Serial.print(F("bitreverse32Bit(0x654321) >> 8 =0x"));
+ Serial.print(bitreverse32Bit(0x654321) >> 8, HEX);
+ Serial.print(F(" >> 1 =0x"));
+ Serial.print((bitreverse32Bit(0x654321) >> 8) >> 1, HEX);
+ Serial.print(F(" ~ =0x"));
+ Serial.println((~((bitreverse32Bit(0x654321) >> 8) >> 1)) & 0x7FFFFF, HEX);
+#endif
+
+ delay(DELAY_AFTER_SEND);
+
+# if defined(DECODE_SONY)
+ Serial.println(F("Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600"));
Serial.flush();
- uint32_t tData = (uint32_t) sAddress << 7 | (sCommand & 0x7F);
- IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, tData, SIRCS_12_PROTOCOL, PROTOCOL_IS_LSB_FIRST, 0, 0);
+ IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, (sAddress << 7 | (sCommand & 0x7F)), SIRCS_12_PROTOCOL,
+ PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceive(sAddress & 0x1F, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
+# endif
- Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first"));
+ Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 - timing ratio is 1:2"));
Serial.flush();
IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0);
checkReceivedRawData(0x87654321);
delay(DELAY_AFTER_SEND);
-
# endif // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
# endif // defined(DECODE_DISTANCE_WIDTH)
# if defined(DECODE_MAGIQUEST)
- Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first"));
+ Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864"));
Serial.flush();
# if __INT_WIDTH__ < 32
- tRawData[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left
- tRawData[1] = 0x017619; // We send only 23 bits here! 0x19 is the checksum
- IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData[0], 55,
+ IRRawDataType tRawData1[2];
+ tRawData1[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left
+ tRawData1[1] = 0x017619; // We send only 23 bits here! 0x19 is the checksum
+ IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData1[0], 55,
PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 0, 0);
# else
// 0xD79BFE00 is 0x6BCDFF00 is shifted 1 left
- IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST, 0, 0);
+ IrSender.sendPulseDistanceWidth(38, 287, 864, 576, 576, 287, 864, 0xD79BFE017619, 55, PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 0, 0);
# endif
checkReceive(0xFF00, 0x176);
if (IrReceiver.decodedIRData.decodedRawData != 0x6BCDFF00) {
Serial.print(F("ERROR: Received address=0x"));
-#if (__INT_WIDTH__ < 32)
+# if (__INT_WIDTH__ < 32)
Serial.print(IrReceiver.decodedIRData.decodedRawData, HEX);
-#else
+# else
PrintULL::print(&Serial, IrReceiver.decodedIRData.decodedRawData, HEX);
-#endif
+# endif
Serial.println(F(" != sent address=0x6BCDFF00"));
Serial.println();
}
delay(DELAY_AFTER_SEND);
# endif // defined(DECODE_MAGIQUEST)
+ } // end of once at first loop
+#endif // if FLASHEND >= 0x7FFF
- }
-#endif // if FLASHEND >= 0x3FFF
-
+#if defined(DECODE_NEC)
Serial.println(F("Send Onkyo (NEC with 16 bit command)"));
Serial.flush();
- IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, 0);
+ IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, sRepeats);
checkReceive(sAddress, (sCommand + 1) << 8 | sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Apple"));
Serial.flush();
- IrSender.sendApple(sAddress & 0xFF, sCommand, 0);
+ IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
+#endif
#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
Serial.println(F("Send Panasonic"));
Serial.flush();
- IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, 0);
+ IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID"));
Serial.flush();
- IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, 0, 0x4711);
+ IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Kaseikyo_Denon variant"));
Serial.flush();
- IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, 0);
+ IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFFF, sCommand);
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_DENON)
- Serial.println(F("Send Denon"));
+ Serial.println(F("Send Denon with repeats"));
Serial.flush();
- IrSender.sendDenon(sAddress & 0x1F, sCommand, 0);
+ IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
- Serial.println(F("Send Denon/Sharp variant"));
+ Serial.println(F("Send Denon/Sharp variant with repeats"));
Serial.flush();
- IrSender.sendSharp(sAddress & 0x1F, sCommand, 0);
+ IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats);
checkReceive(sAddress & 0x1F, sCommand);
delay(DELAY_AFTER_SEND);
#endif
@@ -692,19 +817,19 @@ 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, 0); // SIRCS_12_PROTOCOL is default
+ IrSender.sendSony(sAddress & 0x1F, sCommand, sRepeats); // SIRCS_12_PROTOCOL is default
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, 0, SIRCS_15_PROTOCOL);
+ IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL);
checkReceive(sAddress & 0xFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits"));
Serial.flush();
- IrSender.sendSony(sAddress & 0x1FFF, sCommand, 0, SIRCS_20_PROTOCOL);
+ IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL);
checkReceive(sAddress & 0x1FFF, sCommand & 0x7F);
delay(DELAY_AFTER_SEND);
#endif
@@ -712,19 +837,19 @@ void loop() {
#if defined(DECODE_SAMSUNG)
Serial.println(F("Send Samsung 8 bit command and 8 bit address"));
Serial.flush();
- IrSender.sendSamsung(sAddress & 0xFF, sCommand, 0);
+ IrSender.sendSamsung(sAddress & 0xFF, sCommand, sRepeats);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Samsung 16 bit command and address"));
Serial.flush();
- IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, 0);
+ IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats);
checkReceive(sAddress, s16BitCommand);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send Samsung48 16 bit command"));
Serial.flush();
- IrSender.sendSamsung48(sAddress, s16BitCommand, 0);
+ IrSender.sendSamsung48(sAddress, s16BitCommand, sRepeats);
checkReceive(sAddress, s16BitCommand);
delay(DELAY_AFTER_SEND);
#endif
@@ -732,41 +857,67 @@ void loop() {
#if defined(DECODE_RC5)
Serial.println(F("Send RC5"));
Serial.flush();
- IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, 0, true); // 5 address, 6 command bits
+ IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits
checkReceive(sAddress & 0x1F, sCommand & 0x3F);
delay(DELAY_AFTER_SEND);
Serial.println(F("Send RC5X with 7.th MSB of command set"));
Serial.flush();
- IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, 0, true); // 5 address, 7 command bits
+ IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits
checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40);
delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_RC6)
Serial.println(F("Send RC6"));
- // RC6 check does not work stable without the flush
Serial.flush();
- IrSender.sendRC6(sAddress & 0xFF, sCommand, 0, true);
+ sLastSendToggleValue = sAddress & 0x01; // to modify toggling at each loop
+
+ IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true);
checkReceive(sAddress & 0xFF, sCommand);
delay(DELAY_AFTER_SEND);
+
+ Serial.println(F("Send RC6A with 14 bit 0x2711 as extra"));
+ Serial.flush();
+ IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true);
+ checkReceive(sAddress & 0xFF, sCommand);
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_MAGIQUEST)
+ uint32_t tWandId = 0x6BCD0000 | (uint32_t) sAddress;
+ Serial.print(F("Send MagiQuest, WandId=0x"));
+ Serial.println(tWandId, HEX);
+ Serial.flush();
+ IrSender.sendMagiQuest(tWandId, s16BitCommand); // we have 31 bit address
+ checkReceive(sAddress, s16BitCommand & 0x1FF); // we have 9 bit command
+ delay(DELAY_AFTER_SEND);
+#endif
+
+#if defined(DECODE_LEGO_PF)
+ Serial.println(F("Send Lego with 2 channel and with 4 command bits"));
+ Serial.flush();
+ IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, false);
+ checkReceive(sAddress & 0x0F, (sCommand | (LEGO_MODE_COMBO << LEGO_COMMAND_BITS)) & 0x1F);
+ delay(DELAY_AFTER_SEND);
#endif
#if defined(DECODE_BEO)
- Serial.println(F("Send Bang&Olufsen"));
+ Serial.println(F("Send Bang&Olufsen / originally with 455 kHz"));
Serial.flush();
- IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0);
+ IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, sRepeats);
# 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 the first 6 entries, which results in rawData 0x0"));
IrReceiver.printIRResultRawFormatted(&Serial, true);
- uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen;
- IrReceiver.decodedIRData.rawDataPtr->rawlen = 6;
+ Serial.println(F("- Now try to decode the first 6 entries, which results in rawData 0x0"));
+ uint8_t tOriginalRawlen = IrReceiver.irparams.rawlen;
+ IrReceiver.decodedIRData.rawlen = 6;
+ IrReceiver.irparams.rawlen = 6;
/*
* decode first part / AGC part of frame
*/
- IrReceiver.decode(); // sets IrReceiver.decodedIRData.rawlen to 6
+ IrReceiver.decode();
IrReceiver.printIRResultShort(&Serial); // -> Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first
// Remove trailing 6 entries for second decode try
@@ -775,23 +926,16 @@ void loop() {
F(
"- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode"));
IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6;
- IrReceiver.decodedIRData.rawDataPtr->rawlen = tOriginalRawlen - 6;
+ IrReceiver.irparams.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];
+ IrReceiver.irparams.rawbuf[i] = IrReceiver.irparams.rawbuf[i + 6];
}
+ IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0];
# endif
checkReceive(sAddress & 0x0FF, sCommand);
delay(DELAY_AFTER_SEND);
#endif
-#if defined(DECODE_MAGIQUEST)
- Serial.println(F("Send MagiQuest"));
- Serial.flush();
- IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address
- checkReceive(sAddress, s16BitCommand & 0x1FF); // we have 9 bit command
- delay(DELAY_AFTER_SEND);
-#endif
-
/*
* Next example how to use the IrSender.write function
*/
@@ -810,7 +954,7 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
- IrSender.write(&IRSendData, 0);
+ IrSender.write(&IRSendData, sRepeats);
checkReceive(IRSendData.address & 0xFF, IRSendData.command);
delay(DELAY_AFTER_SEND);
#endif
@@ -833,7 +977,7 @@ void loop() {
IRSendData.protocol = BOSEWAVE;
Serial.println(F("Send Bosewave with no address and 8 command bits"));
Serial.flush();
- IrSender.write(&IRSendData, 0);
+ IrSender.write(&IRSendData, sRepeats);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif
@@ -843,26 +987,18 @@ void loop() {
Serial.print(F("Send "));
Serial.println(getProtocolString(IRSendData.protocol));
Serial.flush();
- IrSender.write(&IRSendData, 0);
+ IrSender.write(&IRSendData, sRepeats);
checkReceive(0, IRSendData.command & 0xFF);
delay(DELAY_AFTER_SEND);
#endif
- /*
- * LEGO is skipped, since it is difficult to receive because of its short marks and spaces
- */
-// Serial.println(F("Send Lego with 2 channel and with 4 command bits"));
-// Serial.flush();
-// IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, true);
-// checkReceive(sAddress, sCommand); // never has success for Lego protocol :-(
-// delay(DELAY_AFTER_SEND);
/*
* Force buffer overflow
*/
Serial.println(F("Force buffer overflow by sending 450 marks and spaces"));
- for (unsigned int i = 0; i < 225; ++i) {
- // 400 + 400 should be received as 8/8 and sometimes as 9/7 or 7/9 if compensation by MARK_EXCESS_MICROS is optimal.
+ for (unsigned int i = 0; i < 225; ++i) { // 225 because we send 2 entries per loop
// 210 + 540 = 750 should be received as 5/10 or 4/11 if compensation by MARK_EXCESS_MICROS is optimal.
+ // 400 + 400 should be received as 8/8 and sometimes as 9/7 or 7/9 if compensation by MARK_EXCESS_MICROS is optimal.
IrSender.mark(210); // 8 pulses at 38 kHz
IrSender.space(540); // to fill up to 750 us
}
@@ -881,6 +1017,14 @@ void loop() {
if (sRepeats > 4) {
sRepeats = 4;
}
+
+ /*
+ * Test stop and start of 50 us receiver timer
+ */
+ Serial.println(F("Stop receiver"));
+ IrReceiver.stop();
delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop
+ Serial.println(F("Start receiver"));
+ IrReceiver.start(); // For ESP32 timerEnableReceiveInterrupt() is sufficient here, since timer is not reconfigured by another task
}
diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log
index e96beb259..24cdb3168 100644
--- a/examples/UnitTest/UnitTest.log
+++ b/examples/UnitTest/UnitTest.log
@@ -1,8 +1,8 @@
-START ../src/UnitTest.cpp from Jun 22 2024
-Using library version 4.4.0
-Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave, MagiQuest, Universal Pulse Distance Width, Hash at pin 2
+START ../src/UnitTest.cpp from Aug 25 2025
+Using library version 4.5.0
+Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Lego Power Functions, Bosewave, MagiQuest, Universal Pulse Distance Width, Hash at pin 2
Use ReceiveCompleteCallback
-Receive buffer length is 200
+Receive buffer length is 400
Send IR signals at pin 3
If you connect debug pin 5 to ground, raw data is always printed
Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us
@@ -12,624 +12,807 @@ Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000
address=0xFFF1 command=0x76
Send NEC with 8 bit address
-Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
+Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=754000us, Duration=67900us
Send with: IrSender.sendNEC(0xF1, 0x76, );
-rawData[68]:
- -1049200
- +8900,-445
- + 600,-1600 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,- 550 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+rawIRTimings[68]:
+ -754000
+ +8950,-4400
+ + 650,-1600 + 600,- 500 + 650,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ + 650,- 450 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,- 500 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,- 550 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,-1600 + 650,- 450 + 650,- 500 + 650,-1600
+ + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1650
+ 600
-Sum: 67800
+Duration=67900us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764850us, Duration=73400us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1058500
- +8950,-4450
- + 550,-1650 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1600
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 600
-Sum: 73350
+rawIRTimings[68]:
+ -764850
+ +8900,-4400
+ + 650,-1600 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,-1650 + 650,-1600 + 650,-1550 + 600,-1650
+ + 650,-1600 + 650,-1550 + 650,-1600 + 650,-1600
+ + 600,-1600 + 600,-1650 + 600,-1650 + 650,-1600
+ + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450
+ + 650,-1600 + 650,-1600 + 600,-1650 + 650,- 500
+ + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650
+Duration=73400us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=765200us, Duration=73450us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
-rawData[68]:
- -1059050
+rawIRTimings[68]:
+ -765200
+8950,-4400
- + 600,-1600 + 600,- 550 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
- + 600,- 550 + 600,-1600 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,- 550 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
+ + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,-1600 + 600,-1650 + 600,-1650 + 650,-1550
+ + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,- 550 + 600,-1600 + 600,-1650 + 650,- 500
+ + 600,-1650 + 650,-1600 + 600,-1600 + 650,- 500
+ + 600,-1650 + 650,- 450 + 650,- 500 + 650,-1600
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600
+ + 650
+Duration=73450us
+
+
+Send arbitrary raw data with 1 repeat and exact timing (16 bit array format) with sendRaw()
+PULSE_DISTANCE_WIDTH: Mark 3050 is longer than maximum 2500 us. Index=13
+Protocol=UNKNOWN Hash=0x333F4BD5 9 bits (incl. gap and start) received
+Send with:
+ uint16_t rawIRTimings[17] = {8980,4420, 580,920, 1030,470, 580,1920, 2080,420, 630,2870, 3030,470, 580,170, 330}; // Protocol=UNKNOWN Hash=0x333F4BD5 9 bits (incl. gap and start) received
+ IrSender.sendRaw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, , );
+rawIRTimings[18]:
+ -770450
+ +9000,-4400
+ + 600,- 900 +1050,- 450 + 600,-1900 +2100,- 400
+ + 650,-2850 +3050,- 450 + 600,- 150 + 350
+Duration=29500us
+
+ERROR: Unknown protocol
+
+Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto()
+Protocol=NEC Address=0x80, Command=0x45, Raw-Data=0xBA457F80, 32 bits, LSB first, Gap=756450us, Duration=68550us
+Send with: IrSender.sendNEC(0x80, 0x45, );
+rawIRTimings[68]:
+ -756450
+ +9100,-4350
+ + 700,- 450 + 700,- 500 + 650,- 550 + 600,- 550
+ + 700,- 450 + 700,- 500 + 650,- 500 + 700,-1550
+ + 700,-1550 + 700,-1500 + 700,-1550 + 650,-1550
+ + 700,-1550 + 650,-1600 + 650,-1550 + 650,- 550
+ + 650,-1550 + 700,- 450 + 650,-1600 + 700,- 450
+ + 700,- 500 + 650,- 500 + 700,-1550 + 700,- 450
+ + 800,- 350 + 750,-1500 + 650,- 500 + 650,-1600
+ + 700,-1500 + 700,-1550 + 700,- 500 + 650,-1550
+ + 700
+Duration=68550us
+
+
+Send NEC data with 8 bit address=0xFB04, command 0x08, 1 repeat and exact timing (16 bit array format) with sendRaw_P()
+Protocol=NEC Address=0x4, Command=0x8, Raw-Data=0xF708FB04, 32 bits, LSB first, Gap=772400us, Duration=68100us
+Send with: IrSender.sendNEC(0x4, 0x8, );
+rawIRTimings[68]:
+ -772400
+ +8950,-4450
+ + 650,- 500 + 600,- 550 + 600,-1650 + 650,- 450
+ + 650,- 500 + 650,- 450 + 650,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,- 500 + 600,-1650
+ + 600,-1650 + 650,-1600 + 650,-1600 + 700,-1550
+ + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1650
+ + 650,- 500 + 650,- 500 + 600,- 500 + 600,- 550
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ 600
-Sum: 73300
+Duration=68100us
+
-Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+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, Gap=769500us, Duration=55700us
+Send with: IrSender.sendOnkyo(0x102, 0x304, );
+rawIRTimings[68]:
+ -769500
+ +8900,-4450
+ + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,-1650 + 600,- 500 + 650,- 500 + 600,- 500
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,-1650 + 650,- 450
+ + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1650 + 650,-1600 + 600,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650
+Duration=55700us
+
+
+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, Gap=771400us, Duration=61250us
+Send with: IrSender.sendNEC(0x102, 0x34, );
+rawIRTimings[68]:
+ -771400
+ +8950,-4400
+ + 650,- 500 + 650,-1600 + 650,- 450 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 600,-1650 + 650,- 450 + 650,- 500 + 650,- 500
+ + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500
+ + 600,- 550 + 650,- 500 + 600,-1600 + 650,- 500
+ + 650,-1600 + 650,-1600 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1600 + 650,- 500 + 600,-1650
+ + 650,- 450 + 650,- 500 + 650,-1600 + 600,-1600
+ + 650
+Duration=61250us
+
+
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=770850us, Duration=55000us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1062700
+rawIRTimings[100]:
+ -770850
+3450,-1700
- + 450,- 450 + 450,-1250 + 450,- 400 + 500,- 400
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 400 + 450,- 450 + 450,- 400
- + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 400
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,- 400
- + 500,-1250 + 450,-1250 + 450,- 450 + 450,-1250
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,- 400
- + 500,- 400 + 450,- 400 + 450,- 400 + 500,- 400
- + 450,- 400 + 500,- 400 + 450,- 400 + 450,- 400
- + 500,-1250 + 450,- 400 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 400 + 450,- 450 + 450,- 400
- + 450,- 400 + 500,-1250 + 450,- 400 + 500,-1250
- + 450
-Sum: 54150
+ + 500,- 400 + 500,-1250 + 500,- 400 + 450,- 450
+ + 450,- 400 + 500,- 400 + 500,- 400 + 450,- 400
+ + 550,- 350 + 500,- 350 + 500,- 400 + 500,- 400
+ + 450,- 400 + 500,-1250 + 500,- 400 + 450,- 450
+ + 450,- 400 + 500,- 400 + 500,- 400 + 450,- 450
+ + 500,-1200 + 500,-1250 + 500,- 350 + 450,-1300
+ + 500,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 450,- 450
+ + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 400
+ + 500,- 350 + 500,-1250 + 550,- 350 + 500,-1250
+ + 500
+Duration=55000us
+
-Send Panasonic 0xB, 0x10 as 48 bit PulseDistance
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400
-LSB first
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=787500us, Duration=54050us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1079300
- +3450,-1650
- + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,-1200 + 500,-1200 + 500,- 350 + 500,-1200
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 400
- + 450,- 400 + 450,- 400 + 450,- 350 + 500,- 350
- + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350
+rawIRTimings[100]:
+ -787500
+ +3450,-1700
+ + 550,- 350 + 450,-1250 + 500,- 350 + 500,- 400
+ + 500,- 350 + 500,- 350 + 550,- 350 + 450,- 400
+ + 550,- 300 + 550,- 350 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,-1200 + 500,- 400 + 500,- 350
+ + 500,- 350 + 500,- 350 + 550,- 350 + 500,- 350
+ + 550,-1150 + 500,-1200 + 500,- 350 + 500,-1200
+ + 550,- 350 + 500,- 350 + 500,- 350 + 500,- 400
+ + 500,- 350 + 500,- 350 + 550,- 350 + 500,- 400
+ 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 400 + 450,-1200 + 500,- 350 + 500,-1200
- + 500
-Sum: 53200
+ + 550,-1200 + 500,- 350 + 550,- 300 + 550,- 350
+ + 500,- 350 + 550,- 300 + 550,- 350 + 500,- 350
+ + 500,- 350 + 550,-1150 + 550,- 300 + 550,-1200
+ + 550
+Duration=54050us
+
-MSB first
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first
+Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=780150us, Duration=54100us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
-rawData[100]:
- -1074200
- +3450,-1650
- + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,-1200 + 500,-1200 + 500,- 350 + 500,-1200
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400
- + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 350
- + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350
- + 500,- 400 + 450,-1200 + 500,- 350 + 500,-1200
- + 500
-Sum: 53200
+rawIRTimings[100]:
+ -780150
+ +3450,-1700
+ + 500,- 400 + 500,-1200 + 500,- 350 + 500,- 400
+ + 500,- 350 + 550,- 300 + 500,- 400 + 500,- 350
+ + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350
+ + 500,- 400 + 500,-1200 + 500,- 350 + 500,- 350
+ + 550,- 350 + 550,- 300 + 500,- 400 + 500,- 300
+ + 500,-1250 + 500,-1200 + 500,- 350 + 500,-1200
+ + 500,- 400 + 500,- 350 + 550,- 350 + 500,- 350
+ + 500,- 350 + 500,- 350 + 550,- 350 + 550,- 350
+ + 500,- 350 + 500,- 350 + 500,- 350 + 600,- 300
+ + 500,-1200 + 550,- 300 + 550,- 350 + 500,- 350
+ + 500,- 400 + 550,- 300 + 500,- 350 + 550,- 350
+ + 500,- 350 + 550,-1150 + 500,- 400 + 500,-1200
+ + 550
+Duration=54100us
+
-Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first
-Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
+Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600
+Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=786950us, Duration=139050us
Send on a 8 bit platform with:
- uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
- IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
-rawData[148]:
- -1079150
- +8850,-4400
- + 550,-1650 + 600,- 550 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,-1650 + 600,- 550 + 600,- 550
- + 600,-1650 + 600,-1650 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,-1650 + 600,- 550
- + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550
- + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,- 550 + 600,-1650
- + 600,-1650 + 600,- 550 + 600,- 550 + 600,-1650
- + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650
- + 600,- 550 + 600,- 550 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1650
- + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650
- + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1700
- + 550,- 550 + 600,-1650 + 600,- 550 + 600,-1650
- + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550
+ uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
+ IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4400, 650, 1600, 650, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[148]:
+ -786950
+ +8900,-4400
+ + 650,-1600 + 600,- 550 + 600,- 550 + 600,- 600
+ + 600,- 550 + 650,-1600 + 650,- 500 + 650,- 550
+ + 650,-1600 + 600,-1650 + 650,- 500 + 650,- 550
+ + 600,- 550 + 650,- 500 + 600,-1650 + 650,- 500
+ + 650,-1600 + 600,- 550 + 650,-1600 + 650,- 550
+ + 600,- 550 + 600,-1650 + 650,-1600 + 600,- 550
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 550
+ + 650,- 500 + 650,- 550 + 600,- 550 + 650,-1600
+ + 700,-1600 + 650,- 500 + 650,- 500 + 650,-1600
+ + 650,- 550 + 600,-1650 + 650,- 500 + 650,-1600
+ + 650,-1600 + 650,-1600 + 650,- 500 + 700,-1550
+ + 700,- 500 + 650,- 500 + 650,-1600 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,-1650 + 700,-1550
+ + 700,- 500 + 650,-1600 + 650,-1600 + 600,-1650
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1650
+ + 600,- 550 + 650,-1600 + 600,- 550 + 650,-1650
+ + 600,- 550 + 600,-1650 + 650,- 500 + 650,-1600
+ + 600,-1650 + 650,- 550 + 600,-1650 + 550,- 600
+ 600
-Sum: 138350
+Duration=139050us
-Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first
-Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300
+Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822650us, Duration=49000us
Send on a 8 bit platform with:
- uint32_t tRawData[]={0x87654321, 0xDCBA9};
- IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
-rawData[108]:
- -1116150
- + 300,- 600
- + 350,- 550 + 650,- 250 + 650,- 250 + 650,- 250
- + 650,- 250 + 350,- 550 + 650,- 250 + 650,- 250
- + 350,- 600 + 300,- 600 + 650,- 250 + 650,- 250
- + 650,- 250 + 650,- 250 + 350,- 550 + 650,- 250
- + 350,- 600 + 600,- 250 + 350,- 600 + 600,- 250
- + 650,- 250 + 350,- 600 + 350,- 550 + 600,- 300
- + 350,- 550 + 350,- 550 + 350,- 550 + 650,- 250
- + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 600
- + 350,- 550 + 650,- 250 + 650,- 250 + 350,- 550
- + 650,- 250 + 350,- 600 + 600,- 300 + 350,- 550
- + 350,- 550 + 350,- 550 + 650,- 250 + 350,- 550
- + 650,- 250 + 650,- 250 + 350,- 550 + 350,- 600
- + 350,- 550 + 600,- 300 + 350,- 550 + 350,- 550
- + 350
-Sum: 48300
-
-Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data
-Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first
+ uint32_t tRawData[]={0x87654321, 0xDCBA9};
+ IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 700, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[108]:
+ -822650
+ + 350,- 600
+ + 350,- 550 + 650,- 300 + 600,- 250 + 700,- 250
+ + 700,- 150 + 450,- 500 + 700,- 250 + 650,- 250
+ + 350,- 550 + 400,- 550 + 700,- 200 + 700,- 250
+ + 650,- 200 + 750,- 250 + 350,- 550 + 650,- 300
+ + 350,- 550 + 650,- 250 + 350,- 550 + 700,- 250
+ + 700,- 150 + 400,- 550 + 350,- 550 + 650,- 300
+ + 300,- 600 + 350,- 550 + 400,- 500 + 700,- 200
+ + 700,- 200 + 700,- 300 + 650,- 250 + 350,- 550
+ + 400,- 500 + 650,- 300 + 700,- 200 + 350,- 600
+ + 650,- 200 + 450,- 550 + 650,- 250 + 350,- 550
+ + 400,- 500 + 400,- 550 + 650,- 250 + 400,- 500
+ + 700,- 250 + 650,- 300 + 350,- 500 + 350,- 600
+ + 350,- 550 + 700,- 200 + 400,- 550 + 350,- 550
+ + 400
+Duration=49000us
+
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600
+Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=802900us, Duration=49250us
Send on a 8 bit platform with:
- uint32_t tRawData[]={0x87654321, 0xDCBA9};
- IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
-rawData[108]:
- -1095900
- + 350,- 550
- + 350,- 550 + 650,- 250 + 650,- 250 + 650,- 250
- + 650,- 250 + 350,- 600 + 600,- 300 + 600,- 300
- + 350,- 550 + 350,- 550 + 600,- 300 + 600,- 300
- + 600,- 300 + 600,- 300 + 300,- 600 + 600,- 300
- + 350,- 550 + 600,- 300 + 350,- 550 + 600,- 300
- + 600,- 300 + 350,- 550 + 350,- 550 + 650,- 250
- + 350,- 550 + 350,- 600 + 300,- 600 + 600,- 300
- + 600,- 300 + 600,- 250 + 650,- 300 + 300,- 600
- + 350,- 550 + 650,- 250 + 650,- 250 + 350,- 600
- + 600,- 300 + 350,- 550 + 600,- 300 + 350,- 550
- + 350,- 550 + 350,- 550 + 650,- 250 + 350,- 550
- + 650,- 250 + 650,- 250 + 350,- 550 + 350,- 550
- + 350,- 600 + 600,- 250 + 400,- 550 + 300,- 600
- + 600
-Sum: 48500
+ uint32_t tRawData[]={0x87654321, 0xDCBA9};
+ IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 700, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , );
+rawIRTimings[108]:
+ -802900
+ + 350,- 600
+ + 350,- 550 + 650,- 300 + 650,- 200 + 750,- 150
+ + 700,- 300 + 350,- 550 + 700,- 250 + 650,- 250
+ + 400,- 500 + 350,- 550 + 700,- 200 + 700,- 250
+ + 650,- 300 + 650,- 200 + 400,- 550 + 700,- 200
+ + 400,- 500 + 650,- 300 + 350,- 550 + 650,- 300
+ + 650,- 250 + 350,- 550 + 350,- 550 + 650,- 250
+ + 400,- 550 + 350,- 550 + 400,- 500 + 700,- 200
+ + 700,- 200 + 700,- 250 + 650,- 300 + 350,- 550
+ + 350,- 600 + 700,- 250 + 650,- 200 + 400,- 550
+ + 650,- 250 + 400,- 500 + 700,- 250 + 350,- 550
+ + 350,- 550 + 350,- 550 + 700,- 250 + 350,- 550
+ + 700,- 250 + 650,- 250 + 350,- 550 + 350,- 550
+ + 400,- 500 + 650,- 300 + 350,- 550 + 400,- 500
+ + 700
+Duration=49250us
+
-Send ASCII 7 bit PulseDistanceWidth LSB first
-Protocol=PulseDistance Raw-Data=0x76 7 bits LSB first
-Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 5950, 500, 550, 1450, 1550, 500, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , );
+Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500
+Protocol=PulseDistance, Raw-Data=0x76, 7 bits, LSB first, Gap=800750us, Duration=20950us
+Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 6000, 450, 550, 1450, 1550, 450, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , );
rawData[18]:
- -1092450
- +5950,- 500
- +1500,- 500 + 500,-1450 + 550,-1450 +1550,- 450
+ -800750
+ +6000,- 450
+ +1550,- 450 + 500,-1450 + 550,-1450 +1550,- 450
+ 550,-1450 + 550,-1450 + 550,-1450 + 550
-Sum: 20950
+Duration=20950us
+
+
+Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275
+Protocol=PulseDistance, Raw-Data=0x3D9EAC, 23 bits, LSB first, Gap=747400us, Duration=42350us
+Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 550, 1250, 500, 1250, 1300, 400, 0x3D9EAC, 23, PROTOCOL_IS_LSB_FIRST, , );
+rawData[50]:
+ -747400
+ + 550,-1250
+ +1300,- 400 +1300,- 400 + 450,-1250 + 450,-1250
+ +1300,- 450 + 450,-1250 +1300,- 350 + 500,-1200
+ +1350,- 400 + 450,-1250 + 500,-1200 + 500,-1200
+ + 500,-1250 +1300,- 400 +1300,- 350 + 500,-1250
+ + 450,-1250 +1300,- 400 + 450,-1250 + 500,-1200
+ + 500,-1200 + 500,-1200 +1350,- 400 +1300
+Duration=42350us
-Send Sony12 as PulseWidth LSB first
-Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
+
+Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600
+Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=744650us, Duration=21050us
Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
rawData[26]:
- -1036550
+ -744650
+2450,- 600
+ 600,- 550 +1250,- 550 +1250,- 550 + 650,- 550
+1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
+ 650,- 550 + 650,- 550 + 650,- 550 +1250
-Sum: 21050
+Duration=21050us
+
-Send 32 bit PulseWidth 0x87654321 LSB first
-Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
+Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300
+Protocol=PulseWidth, Raw-Data=0x87654321, 32 bits, LSB first, Gap=744500us, Duration=24550us
Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1050, 500, 650, 250, 350, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , );
rawData[66]:
- -1036150
+ -744500
+1050,- 500
- + 600,- 300 + 350,- 250 + 350,- 250 + 350,- 250
- + 350,- 300 + 600,- 300 + 350,- 250 + 350,- 250
- + 650,- 250 + 650,- 250 + 350,- 300 + 350,- 250
- + 350,- 250 + 350,- 300 + 600,- 300 + 300,- 300
+ + 600,- 250 + 400,- 250 + 350,- 250 + 350,- 250
+ + 350,- 250 + 650,- 250 + 400,- 250 + 350,- 250
+ + 650,- 250 + 650,- 250 + 350,- 250 + 350,- 250
+ + 400,- 250 + 350,- 250 + 600,- 300 + 350,- 250
+ 600,- 300 + 350,- 250 + 600,- 300 + 350,- 250
- + 350,- 250 + 650,- 250 + 650,- 250 + 350,- 250
- + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 300
- + 350,- 250 + 350,- 250 + 350,- 250 + 650
-Sum: 24600
+ + 400,- 200 + 650,- 250 + 650,- 250 + 400,- 250
+ + 600,- 250 + 650,- 250 + 650,- 250 + 400,- 250
+ + 350,- 250 + 350,- 250 + 400,- 200 + 650
+Duration=24550us
+
-Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first
-Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
+Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864
+Protocol=MagiQuest Address=0xFF00, Command=0x176, Raw-Data=0x6BCDFF00, 56 bits, MSB first, Gap=773750us, Duration=63850us
Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, );
rawData[112]:
- -1065600
- + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
+ -773750
+ + 350,- 850 + 300,- 850 + 300,- 800 + 350,- 800
+ 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
- + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550
+ + 650,- 500 + 600,- 550 + 350,- 800 + 600,- 550
+ 350,- 800 + 600,- 550 + 600,- 550 + 600,- 550
- + 600,- 550 + 350,- 800 + 350,- 800 + 600,- 550
- + 600,- 550 + 350,- 800 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,- 550 + 300,- 850
- + 350,- 850 + 300,- 850 + 300,- 800 + 350,- 800
+ + 600,- 550 + 350,- 850 + 300,- 800 + 650,- 500
+ + 650,- 500 + 350,- 800 + 650,- 550 + 600,- 500
+ + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500
+ + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800
+ + 300,- 900 + 300,- 850 + 300,- 800 + 350,- 800
+ 350,- 800 + 350,- 800 + 350,- 800 + 600,- 550
- + 350,- 800 + 650,- 500 + 600,- 600 + 550,- 550
- + 300,- 850 + 600,- 550 + 600,- 550 + 350,- 800
- + 300,- 850 + 350,- 800 + 350,- 800 + 600,- 550
+ + 350,- 800 + 600,- 550 + 650,- 500 + 650,- 500
+ + 350,- 800 + 650,- 500 + 650,- 500 + 350,- 800
+ + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 500
+ 600,- 550 + 350,- 800 + 350,- 800 + 600
-Sum: 63850
+Duration=63850us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first
+Protocol=Onkyo Address=0xFFF1, Command=0x7776, Raw-Data=0x7776FFF1, 32 bits, LSB first, Gap=790650us, Duration=76650us
Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, );
rawData[68]:
- -1084150
+ -790650
+8950,-4400
- + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1650
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,-1600 + 600,-1650 + 650,-1600
+ + 650,- 450 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
+ 600
-Sum: 76750
+Duration=76650us
+
Send Apple
-Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first
+Protocol=Apple Address=0xF1, Command=0x76, Raw-Data=0xF17687EE, 32 bits, LSB first, Gap=763800us, Duration=72250us
Send with: IrSender.sendApple(0xF1, 0x76, );
rawData[68]:
- -1058150
- +8900,-4450
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,-1600
- + 600,- 550 + 600,-1650 + 600,-1600 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,-1600 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
+ -763800
+ +8950,-4400
+ + 650,- 500 + 650,-1550 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,-1650 + 600,-1600 + 600,-1650 + 650,- 500
+ + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1600 + 600,-1650 + 650,-1600
+ 600
-Sum: 72200
+Duration=72250us
+
Send Panasonic
-Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+Protocol=Panasonic Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=763550us, Duration=64400us
Send with: IrSender.sendPanasonic(0xFF1, 0x76, );
rawData[100]:
- -1057800
+ -763550
+3450,-1700
- + 450,- 400 + 500,-1250 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 400
- + 450,- 450 + 450,- 400 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,-1300 + 450,- 400 + 450,- 400
- + 500,- 400 + 450,- 400 + 450,- 400 + 500,- 400
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,-1300 + 450,-1250
- + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1300
- + 450,- 400 + 450,-1250 + 450,-1300 + 450,- 400
- + 450,-1250 + 450,-1300 + 450,-1250 + 500,- 400
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,-1250
- + 450,-1300 + 450,- 400 + 450,- 400 + 500,-1250
+ + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 350
+ + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350
+ + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400
+ + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,-1250 + 500,-1200 + 500,-1200 + 500,-1250
+ + 500,-1200 + 500,-1250 + 450,-1250 + 450,-1300
+ + 450,- 400 + 500,-1250 + 450,-1250 + 450,- 450
+ + 450,-1250 + 450,-1300 + 450,-1250 + 500,- 350
+ + 500,-1250 + 500,- 350 + 500,- 400 + 450,-1250
+ + 450,-1300 + 450,- 400 + 500,- 350 + 500,-1250
+ 450
-Sum: 64400
+Duration=64400us
+
Send Kaseikyo with 0x4711 as Vendor ID
-Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first
+Protocol=Kaseikyo Address=0xFF1, Command=0x76, Extra=0x4711, Raw-Data=0x9A76FF13, 48 bits, LSB first, Gap=783450us, Duration=69550us
Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711);
rawData[100]:
- -1078000
- +3450,-1700
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 450
- + 450,-1250 + 450,- 400 + 500,- 400 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,-1300 + 450,- 400
- + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 450
- + 450,-1250 + 450,-1300 + 450,- 400 + 450,- 400
- + 500,-1250 + 450,- 400 + 450,- 450 + 450,- 400
+ -783450
+ +3500,-1650
+ + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400
+ + 450,-1250 + 500,- 350 + 500,- 400 + 500,- 350
+ + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400
+ + 500,- 350 + 500,- 400 + 450,-1250 + 500,- 400
+ + 450,-1250 + 500,-1200 + 500,- 400 + 500,- 350
+ + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400
+ 450,-1250 + 450,-1300 + 450,-1250 + 450,-1300
+ 450,-1250 + 450,-1300 + 450,-1250 + 450,-1300
- + 450,- 400 + 450,-1300 + 450,-1250 + 450,- 450
- + 450,-1250 + 450,-1250 + 500,-1250 + 450,- 400
- + 450,- 400 + 500,-1250 + 450,- 400 + 450,-1300
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,-1250
- + 500
-Sum: 69550
+ + 450,- 400 + 500,-1250 + 450,-1250 + 500,- 400
+ + 450,-1250 + 500,-1250 + 450,-1250 + 450,- 450
+ + 450,- 400 + 500,-1200 + 500,- 400 + 450,-1250
+ + 500,-1250 + 450,- 400 + 500,- 350 + 450,-1300
+ + 450
+Duration=69550us
+
Send Kaseikyo_Denon variant
-Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first
+Protocol=Kaseikyo_Denon Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=784200us, Duration=67850us
Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, );
rawData[100]:
- -1078750
- +3450,-1700
- + 500,- 400 + 450,- 400 + 450,-1300 + 450,- 400
- + 450,-1250 + 500,- 400 + 450,-1250 + 500,- 400
- + 450,- 400 + 450,-1250 + 450,- 450 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,- 400 + 500,- 400
- + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 400
+ -784200
+ +3500,-1650
+ + 500,- 400 + 450,- 400 + 500,-1250 + 450,- 400
+ + 500,-1200 + 450,- 450 + 450,-1250 + 450,- 450
+ + 450,- 400 + 500,-1200 + 450,- 450 + 450,- 400
+ + 450,-1250 + 500,-1250 + 450,- 400 + 500,- 400
+ + 450,- 400 + 450,- 400 + 450,- 450 + 450,- 400
+ 450,-1300 + 450,- 400 + 450,- 400 + 450,- 450
- + 450,-1250 + 450,-1300 + 450,-1250 + 450,-1300
- + 450,-1250 + 450,-1300 + 450,-1250 + 450,-1300
- + 450,- 400 + 450,-1300 + 450,-1250 + 450,- 400
- + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400
- + 500,-1250 + 450,- 400 + 450,- 400 + 450,-1300
- + 450,-1250 + 450,- 400 + 500,- 400 + 450,-1250
+ + 500,-1200 + 500,-1250 + 450,-1250 + 450,-1300
+ + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1250
+ + 500,- 350 + 450,-1300 + 450,-1250 + 450,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 500,- 350
+ + 500,-1250 + 500,- 350 + 500,- 350 + 500,-1250
+ + 450,-1250 + 450,- 450 + 450,- 400 + 450,-1250
+ 500
-Sum: 67850
+Duration=67850us
-Send Denon
-Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first
+
+Send Denon with repeats
+Protocol=Denon Address=0x11, Command=0x76, Raw-Data=0xED1, 15 bits, LSB first, Gap=783000us, Duration=23100us
Send with: IrSender.sendDenon(0x11, 0x76, );
rawData[32]:
- -1076500
- + 300,-1750 + 300,- 750 + 300,- 750 + 300,- 750
- + 300,-1750 + 300,- 750 + 300,-1800 + 250,-1800
+ -783000
+ + 250,-1800 + 300,- 750 + 300,- 750 + 300,- 700
+ + 300,-1800 + 300,- 750 + 250,-1800 + 300,-1750
+ 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750
+ 300,- 750 + 300,- 750 + 300,- 750 + 300
-Sum: 23150
+Duration=23100us
-Send Denon/Sharp variant
-Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first
+
+Send Denon/Sharp variant with repeats
+Protocol=Sharp Address=0x11, Command=0x76, Raw-Data=0x2ED1, 15 bits, LSB first, Gap=726000us, Duration=24150us
Send with: IrSender.sendSharp(0x11, 0x76, );
rawData[32]:
- -1018700
- + 300,-1800 + 300,- 750 + 300,- 700 + 300,- 750
- + 300,-1800 + 250,- 750 + 300,-1800 + 250,-1800
+ -726000
+ + 300,-1800 + 300,- 750 + 250,- 750 + 300,- 750
+ + 300,-1750 + 300,- 750 + 300,-1800 + 250,-1800
+ 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750
- + 300,- 750 + 300,- 750 + 300,-1750 + 300
-Sum: 24150
+ + 300,- 750 + 300,-1750 + 300,- 750 + 300
+Duration=24150us
+
Send Sony/SIRCS with 7 command and 5 address bits
-Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
+Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=727100us, Duration=21050us
Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
rawData[26]:
- -1020900
+ -727100
+2450,- 550
+ 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550
+1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
- + 650,- 550 + 650,- 550 + 650,- 550 +1250
-Sum: 21050
+ + 650,- 550 + 650,- 550 + 600,- 600 +1250
+Duration=21050us
+
Send Sony/SIRCS with 7 command and 8 address bits
-Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first
+Protocol=Sony Address=0xF1, Command=0x76, Raw-Data=0x78F6, 15 bits, LSB first, Gap=743250us, Duration=26450us
Send with: IrSender.sendSony(0xF1, 0x76, 2, 15);
rawData[32]:
- -1036650
- +2450,- 550
- + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550
+ -743250
+ +2400,- 600
+ + 650,- 550 +1200,- 600 +1250,- 550 + 650,- 550
+1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
+ 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550
+1250,- 550 +1250,- 550 +1250
-Sum: 26450
+Duration=26450us
+
Send Sony/SIRCS with 7 command and 13 address bits
-Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first
+Protocol=Sony Address=0x1FF1, Command=0x76, Raw-Data=0xFF8F6, 20 bits, LSB first, Gap=746700us, Duration=35400us
Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20);
rawData[42]:
- -1040400
- +2400,- 550
- + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550
+ -746700
+ +2400,- 600
+ + 600,- 600 +1200,- 550 +1250,- 550 + 700,- 500
+1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
- + 650,- 550 + 600,- 600 + 650,- 550 +1250,- 550
+ + 600,- 600 + 650,- 550 + 650,- 550 +1250,- 550
+1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
+1250,- 550 +1250,- 550 +1250,- 550 +1250
-Sum: 35400
+Duration=35400us
+
Send Samsung 8 bit command and 8 bit address
-Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first
+Protocol=Samsung Address=0xF1, Command=0x76, Raw-Data=0x8976F1F1, 32 bits, LSB first, Gap=751750us, Duration=65600us
Send with: IrSender.sendSamsung(0xF1, 0x76, );
rawData[68]:
- -1045200
- +4500,-4400
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600
- + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1600
- + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600
-Sum: 65550
+ -751750
+ +4550,-4350
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 650,-1550 + 650,-1600 + 650,-1600 + 600,-1650
+ + 650,-1600 + 650,- 450 + 650,- 500 + 600,- 500
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,-1600
+ + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
+ + 600,-1650 + 600,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600
+ + 650
+Duration=65600us
+
Send Samsung 16 bit command and address
-Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
+Protocol=Samsung Address=0xFFF1, Command=0x9876, Raw-Data=0x9876FFF1, 32 bits, LSB first, Gap=766100us, Duration=68950us
Send with: IrSender.sendSamsung(0xFFF1, 0x9876, );
rawData[68]:
- -1060350
- +4500,-4450
- + 600,-1600 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650
- + 600,-1650 + 600,-1600 + 650,-1600 + 600,-1650
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,- 550 + 600,-1600 + 600,-1650 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,-1650 + 600,- 550 + 600,- 500 + 600,-1650
- + 600
-Sum: 68950
+ -766100
+ +4500,-4400
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,-1600 + 650,-1550 + 650,-1600 + 600,-1650
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 450 + 600,-1650
+ + 650,-1600 + 600,- 500 + 600,- 550 + 600,-1600
+ + 650
+Duration=68950us
+
Send Samsung48 16 bit command
-Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first
+Protocol=Samsung48 Address=0xFFF1, Command=0x9876, Raw-Data=0x6798, 48 bits, LSB first, Gap=765950us, Duration=95900us
Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, );
rawData[100]:
- -1060250
+ -765950
+4500,-4450
- + 600,-1600 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
- + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1700
- + 550,- 550 + 600,- 500 + 600,- 550 + 600,-1650
- + 600,-1600 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
+ + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ + 600,-1600 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
+ 600,- 500 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500
+ + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 500 + 600,- 550 + 650,- 500 + 600,-1600
+ + 600,- 550 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1650
+ + 550,-1650 + 600,-1650 + 550,-1650 + 650,- 500
+ + 600,- 500 + 600,-1650 + 600,-1650 + 600,- 550
+ 600
-Sum: 95800
+Duration=95900us
+
Send RC5
-Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first
+Protocol=RC5 Address=0x11, Command=0x36, Raw-Data=0x1476, 13 bits, MSB first, Gap=782100us, Duration=23150us
Send with: IrSender.sendRC5(0x11, 0x36, );
rawData[20]:
- -1076800
- + 900,- 900
- +1800,-1750 +1800,- 850 + 950,- 850 + 900,-1750
- + 900,- 850 + 950,- 850 +1800,-1750 + 900,- 900
- +1800
-Sum: 23150
+ -782100
+ + 900,- 850
+ +1850,-1700 +1850,- 850 + 900,- 850 + 950,-1700
+ + 950,- 850 + 950,- 850 +1800,-1700 + 950,- 850
+ +1850
+Duration=23150us
+
Send RC5X with 7.th MSB of command set
-Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first
+Protocol=RC5 Address=0x11, Command=0x76, Toggle=1, Raw-Data=0xC76, 13 bits, MSB first, Gap=742250us, Duration=23100us
Send with: IrSender.sendRC5(0x11, 0x76, );
rawData[20]:
- -1035650
+ -742250
+1800,-1700
- + 950,- 850 +1800,- 850 + 950,- 850 + 900,-1750
- + 950,- 850 + 900,- 850 +1800,-1750 + 950,- 850
+ + 950,- 850 +1800,- 850 + 950,- 850 + 950,-1700
+ + 950,- 850 + 900,- 850 +1850,-1700 + 950,- 850
+1800
-Sum: 23100
+Duration=23100us
+
Send RC6
-Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first
+Protocol=RC6 Address=0xF1, Command=0x76, Raw-Data=0xF176, 20 bits, MSB first, Gap=739650us, Duration=23300us
Send with: IrSender.sendRC6(0xF1, 0x76, );
rawData[36]:
- -1033000
- +2650,- 850
- + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850
- +1350,- 450 + 450,- 400 + 500,- 400 + 500,- 850
+ -739650
+ +2700,- 850
+ + 450,- 900 + 450,- 400 + 500,- 400 + 500,- 850
+ +1400,- 350 + 500,- 400 + 500,- 400 + 500,- 850
+ 500,- 400 + 500,- 400 + 950,- 850 + 950,- 400
+ 500,- 400 + 500,- 850 + 950,- 400 + 500,- 850
+ 500
-Sum: 23300
+Duration=23300us
-Send Bang&Olufsen
-- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
-- Now print raw data and try to decode the first 6 entries, which results in rawData 0x0
-rawData[36]:
- -1033000
- + 250,-2850
- + 250,-2850 + 250,-15250 + 250,-2850 + 250,-9050
- + 250,-6000 + 200,-5950 + 250,-6000 + 200,-2900
- + 250,-5950 + 200,-6000 + 200,-9050 + 250,-2900
- + 250,-9000 + 250,-6000 + 250,-5950 + 250,-2850
- + 250
-Sum: 105700
-Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first
-- 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, );
-rawData[38]:
- -15250
- + 250,-2850
- + 250,-9050 + 250,-6000 + 200,-5950 + 250,-6000
- + 200,-2900 + 250,-5950 + 200,-6000 + 200,-9050
- + 250,-2900 + 250,-9000 + 250,-6000 + 250,-5950
- + 250,-2850 + 250,-9100 + 200,-5950 + 250,-2900
- + 200,-12150 + 250
-Sum: 115000
+Send RC6A with 14 bit 0x2711 as extra
+Protocol=RC6A Address=0xF1, Command=0x76, Extra=0x2711, Toggle=1, Raw-Data=0xA711F176, 35 bits, MSB first, Gap=749700us, Duration=36800us
+Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711);
+rawData[58]:
+ -749700
+ +2700,- 800
+ + 500,- 450 + 450,- 450 + 500,- 800 +1400,-1300
+ + 950,- 800 + 500,- 450 + 900,- 400 + 500,- 400
+ + 500,- 850 + 500,- 400 + 500,- 400 + 950,- 850
+ + 500,- 400 + 500,- 400 + 950,- 450 + 450,- 450
+ + 450,- 450 + 450,- 450 + 450,- 850 + 500,- 400
+ + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400
+ + 500,- 850 + 950,- 400 + 500,- 850 + 500
+Duration=36800us
-Send MagiQuest
-Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first
+
+Send MagiQuest, WandId=0x6BCDFFF1
+Protocol=MagiQuest Address=0xFFF1, Command=0x76, Raw-Data=0x6BCDFFF1, 56 bits, MSB first, Gap=765200us, Duration=64000us
Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, );
rawData[112]:
- -1088700
- + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
+ -765200
+ + 350,- 800 + 350,- 800 + 300,- 850 + 350,- 800
+ 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850
- + 600,- 550 + 600,- 550 + 300,- 850 + 600,- 550
- + 300,- 800 + 650,- 500 + 650,- 500 + 600,- 550
- + 600,- 550 + 350,- 800 + 350,- 800 + 600,- 550
+ + 600,- 550 + 600,- 550 + 350,- 800 + 650,- 500
+ + 350,- 800 + 600,- 550 + 600,- 550 + 600,- 550
+ + 600,- 550 + 350,- 800 + 350,- 800 + 650,- 500
+ 600,- 550 + 350,- 800 + 600,- 550 + 600,- 550
- + 600,- 550 + 600,- 550 + 600,- 550 + 600,- 550
+ + 650,- 500 + 600,- 550 + 600,- 550 + 600,- 550
+ 600,- 550 + 600,- 550 + 600,- 550 + 600,- 550
+ 600,- 550 + 600,- 550 + 600,- 550 + 350,- 800
+ 350,- 800 + 350,- 800 + 600,- 600 + 300,- 850
- + 300,- 800 + 650,- 550 + 600,- 550 + 600,- 550
- + 300,- 800 + 600,- 550 + 600,- 550 + 350,- 850
- + 300,- 800 + 350,- 800 + 600,- 550 + 600,- 550
+ + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550
+ + 350,- 800 + 650,- 550 + 550,- 550 + 300,- 900
+ + 300,- 850 + 300,- 850 + 600,- 550 + 600,- 550
+ 350,- 800 + 600,- 550 + 600,- 550 + 600
-Sum: 63850
+Duration=64000us
+
+
+Send Lego with 2 channel and with 4 command bits
+Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169, 16 bits, MSB first, Gap=791500us, Duration=9950us
+Send with: IrSender.sendLego(0x1, 0x16, );
+rawData[36]:
+ -791500
+ + 250,- 950
+ + 200,- 500 + 250,- 200 + 200,- 200 + 250,- 450
+ + 250,- 200 + 200,- 500 + 200,- 550 + 200,- 200
+ + 200,- 550 + 200,- 200 + 200,- 250 + 200,- 200
+ + 200,- 550 + 200,- 200 + 200,- 250 + 200,- 200
+ + 200
+Duration=9950us
+
+
+Send Bang&Olufsen / originally with 455 kHz
+- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
+rawData[44]:
+ -748300
+ + 250,-2850
+ + 200,-2900 + 250,-12750 + 250,-2900 + 250,-9000
+ + 250,-6000 + 250,-5950 + 200,-6000 + 200,-2900
+ + 200,-6000 + 200,-5950 + 250,-9050 + 250,-2900
+ + 250,-9000 + 250,-6000 + 250,-5950 + 250,-2850
+ + 250,-9050 + 250,-5950 + 250,-2850 + 250,-12150
+ + 250
+Duration=134200us
+
+- Now try to decode the first 6 entries, which results in rawData 0x0
+Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=748300us, Duration=6450us
+
+- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
+Protocol=Bang&Olufsen Address=0xF1, Command=0x76, Raw-Data=0xF176, 16 bits, MSB first, Gap=12750us, Duration=115000us
+Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, );
+rawData[38]:
+ -12750
+ + 250,-2900
+ + 250,-9000 + 250,-6000 + 250,-5950 + 200,-6000
+ + 200,-2900 + 200,-6000 + 200,-5950 + 250,-9050
+ + 250,-2900 + 250,-9000 + 250,-6000 + 250,-5950
+ + 250,-2850 + 250,-9050 + 250,-5950 + 250,-2850
+ + 250,-12150 + 250
+Duration=115000us
+
Send next protocols with IrSender.write
Send JVC
-Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first
+Protocol=JVC Address=0xF1, Command=0x76, Raw-Data=0x76F1, 16 bits, LSB first, Gap=804700us, Duration=40450us
Send with: IrSender.sendJVC(0xF1, 0x76, );
rawData[36]:
- -1085250
+ -804700
+8400,-4150
- + 550,-1550 + 550,- 500 + 550,- 500 + 550,- 500
- + 550,-1550 + 550,-1550 + 550,-1550 + 550,-1550
- + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
- + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
- + 550
-Sum: 40400
+ + 600,-1500 + 600,- 450 + 600,- 450 + 600,- 450
+ + 600,-1500 + 600,-1500 + 600,-1500 + 600,-1500
+ + 600,- 450 + 600,-1500 + 600,-1500 + 600,- 450
+ + 600,-1500 + 600,-1500 + 600,-1500 + 550,- 500
+ + 600
+Duration=40450us
+
Send LG
-Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first
+Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745550us, Duration=59450us
Send with: IrSender.sendLG(0xF1, 0x9876, );
rawData[60]:
- -1039450
- +8950,-4150
- + 550,-1550 + 500,-1550 + 500,-1550 + 550,-1550
- + 500,- 550 + 500,- 550 + 500,- 550 + 500,-1550
- + 550,-1550 + 500,- 550 + 500,- 550 + 500,-1550
- + 550,-1550 + 500,- 550 + 500,- 550 + 500,- 550
- + 500,- 500 + 550,-1550 + 500,-1550 + 550,-1550
+ -745550
+ +9000,-4100
+ + 550,-1550 + 500,-1550 + 550,-1550 + 550,-1500
+ + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
+ + 500,-1550 + 550,- 500 + 550,- 500 + 550,-1550
+ + 500,-1550 + 550,- 500 + 550,- 500 + 550,- 500
+ + 550,- 500 + 550,-1550 + 500,-1550 + 550,-1550
+ 500,- 550 + 500,-1550 + 550,-1550 + 500,- 550
+ 500,-1550 + 550,-1550 + 500,-1550 + 550,- 500
+ 550
-Sum: 59400
+Duration=59450us
+
Send Bosewave with no address and 8 command bits
-Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+Protocol=BoseWave Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=762100us, Duration=26800us
Send with: IrSender.sendBoseWave(0x0, 0x76, );
rawData[36]:
- -1056200
+ -762100
+1050,-1450
- + 550,- 450 + 550,-1400 + 550,-1450 + 550,- 450
- + 550,-1400 + 550,-1450 + 550,-1400 + 550,- 450
- + 550,-1450 + 550,- 450 + 550,- 400 + 550,-1450
- + 550,- 450 + 550,- 450 + 550,- 450 + 550,-1400
+ + 550,- 400 + 600,-1400 + 550,-1450 + 550,- 400
+ + 600,-1400 + 600,-1400 + 550,-1400 + 600,- 400
+ + 550,-1450 + 550,- 400 + 550,- 450 + 550,-1450
+ + 550,- 450 + 550,- 400 + 600,- 400 + 550,-1450
+ 550
-Sum: 26800
+Duration=26800us
+
Send FAST
-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, Gap=746450us, Duration=28900us
Send with: IrSender.sendFAST(0x0, 0x76, );
rawData[36]:
- -1040250
- +2150,-1000
- + 550,- 550 + 550,-1550 + 550,-1500 + 550,- 550
- + 550,-1550 + 550,-1550 + 550,-1550 + 500,- 550
- + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550
- + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
- + 550
-Sum: 28950
+ -746450
+ +2100,-1050
+ + 600,- 450 + 600,-1500 + 600,-1500 + 550,- 500
+ + 600,-1500 + 550,-1550 + 550,-1550 + 550,- 500
+ + 600,-1500 + 550,- 500 + 550,- 500 + 550,-1550
+ + 550,- 500 + 550,- 500 + 550,- 500 + 600,-1550
+ + 500
+Duration=28900us
-Force buffer overflow by sending 280 marks and spaces
+
+Force buffer overflow by sending 450 marks and spaces
Overflow
-Try to increase the "RAW_BUFFER_LENGTH" value of 200 in ../src/UnitTest.cpp
-rawData[200]:
- -1039500
+Try to increase the "RAW_BUFFER_LENGTH" value of 400 in ../src/UnitTest.cpp
+rawData[400]:
+ -745700
+ 200,- 500
- + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 550
- + 200,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 200,- 500 + 250,- 500 + 250,- 550 + 200,- 500
+ + 250,- 500 + 250,- 500 + 250,- 550 + 200,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 550
+ + 200,- 550 + 200,- 550 + 200,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450
+ + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
@@ -637,200 +820,657 @@ rawData[200]:
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 550 + 250,- 500 + 200,- 550
+ + 250,- 500 + 250,- 450 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450
+ 250,- 500 + 250,- 500 + 250
-Sum: 74500
+Duration=149500us
+
ERROR: Unknown protocol
+Stop receiver
+Start receiver
-address=0xF2 command=0x87
+address=0xF2 command=0x87 repeats=1
Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=923450us, Duration=67850us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -3276750
+ -923450
+8950,-4400
- + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600
- + 600,-1650 + 600,- 550 + 600,-1600 + 650,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
- + 550,- 550 + 600,- 500 + 650,- 500 + 600,-1650
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
- + 600
-Sum: 67800
+ + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650
+ + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600
+ + 600,- 550 + 600,- 500 + 650,- 500 + 650,- 450
+ + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600
+ + 650,- 500 + 650,- 500 + 600,- 500 + 600,-1650
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ + 650
+Duration=67850us
+
-Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC2 Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Repeat, Gap=68700us, Duration=67800us
Send with: IrSender.sendNEC2(0xF2, 0x87, );
rawData[68]:
- -65900
- +8900,-4450
- + 550,- 550 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,- 500 + 600,-1650 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 600
-Sum: 67750
+ -68700
+ +8950,-4350
+ + 650,- 500 + 650,-1600 + 600,- 550 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650
+Duration=67800us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=765000us, Duration=67800us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -1060150
- +8900,-4450
- + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600
- + 600,-1650 + 600,- 550 + 600,-1600 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500
- + 600
-Sum: 67800
+ -765000
+ +8950,-4350
+ + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500
+ + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,- 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 + 600,-1600
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650
+Duration=67800us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=764400us, Duration=67800us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -1058650
- +8900,-4400
- + 650,- 500 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 550
- + 600,-1600 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500
+ -764400
+ +8950,-4350
+ + 650,- 500 + 600,-1650 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,- 500 + 650,-1600 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1600 + 600,-1650 + 650,- 450
+ + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550
+ 600
-Sum: 67750
+Duration=67800us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first
+Protocol=Onkyo Address=0xF2, Command=0x8887, Raw-Data=0x888700F2, 32 bits, LSB first, Gap=765000us, Duration=62300us
Send with: IrSender.sendOnkyo(0xF2, 0x8887, );
rawData[68]:
- -1059250
- +8900,-4450
- + 600,- 500 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,- 550
- + 600,- 500 + 650,- 500 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,- 500
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600
- + 600
-Sum: 62150
+ -765000
+ +8950,-4350
+ + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,- 500 + 650,- 450 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650
+Duration=62300us
+
Send Apple
-Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first
+Protocol=Apple Address=0xF2, Command=0x87, Raw-Data=0xF28787EE, 32 bits, LSB first, Gap=763450us, Duration=71150us
Send with: IrSender.sendApple(0xF2, 0x87, );
rawData[68]:
- -1057650
- +8900,-4400
- + 600,- 550 + 600,-1650 + 600,-1600 + 600,-1650
- + 600,- 550 + 600,-1600 + 650,-1600 + 600,-1650
- + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650
- + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600
- + 650
-Sum: 71100
+ -763450
+ +8950,-4400
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600
+ + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600
+Duration=71150us
+
Send Panasonic
-Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first
+Protocol=Panasonic Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=763500us, Duration=59350us
Send with: IrSender.sendPanasonic(0xF2, 0x87, );
rawData[100]:
- -1057750
- +3450,-1700
- + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400
- + 450,- 400 + 500,- 400 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 400
- + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 400
- + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 400
- + 450,- 450 + 450,-1250 + 450,- 400 + 500,- 400
- + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1250
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,- 450
- + 450,-1250 + 450,-1300 + 450,-1250 + 450,- 400
- + 500,- 400 + 450,- 400 + 450,- 450 + 450,-1250
- + 450,- 400 + 500,- 400 + 450,- 400 + 450,-1300
- + 450,- 400 + 450,-1300 + 450,- 400 + 450,-1250
+ -763500
+ +3500,-1700
+ + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,-1250 + 500,- 400 + 450,- 400
+ + 500,- 350 + 500,- 400 + 500,- 350 + 450,- 450
+ + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350
+ + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250
+ + 450,- 450 + 450,- 400 + 500,- 350 + 500,- 400
+ + 500,-1200 + 500,-1250 + 500,-1200 + 500,- 400
+ + 500,- 350 + 450,- 450 + 450,- 400 + 500,-1200
+ + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250
+ + 500,- 350 + 450,-1300 + 450,- 400 + 500,-1200
+ 500
-Sum: 59350
+Duration=59350us
+
Send Kaseikyo with 0x4711 as Vendor ID
-Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F23 48 bits LSB first
+Protocol=Kaseikyo Address=0xF2, Command=0x87, Extra=0x4711, Raw-Data=0xAB870F23, 48 bits, LSB first, Gap=783250us, Duration=66150us
Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711);
rawData[100]:
- -1077750
- +3450,-1700
- + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 400
- + 450,-1300 + 450,- 400 + 450,- 400 + 500,- 400
- + 450,-1250 + 450,-1300 + 450,-1250 + 450,- 400
- + 500,- 400 + 450,- 400 + 450,-1300 + 450,- 400
- + 450,-1250 + 450,-1300 + 450,- 400 + 500,- 400
- + 450,- 400 + 450,-1300 + 450,- 400 + 450,- 400
- + 500,-1250 + 450,-1250 + 450,-1300 + 450,-1250
- + 500,- 400 + 450,- 400 + 450,- 400 + 500,- 400
- + 450,-1300 + 450,-1250 + 500,-1250 + 450,- 400
- + 450,- 400 + 500,- 400 + 450,- 400 + 450,-1300
- + 450,-1250 + 450,-1300 + 450,- 400 + 450,-1300
- + 450,- 400 + 450,-1250 + 450,- 450 + 450,-1250
+ -783250
+ +3500,-1650
+ + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400
+ + 450,-1250 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400
+ + 500,- 400 + 450,- 400 + 500,-1200 + 500,- 400
+ + 450,-1250 + 500,-1250 + 450,- 400 + 500,- 350
+ + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400
+ + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250
+ + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 400
+ + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 400
+ + 450,- 400 + 500,- 350 + 500,- 400 + 500,-1200
+ + 500,-1250 + 500,-1200 + 500,- 400 + 450,-1250
+ + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1250
+ 450
-Sum: 66100
+Duration=66150us
+
Send Kaseikyo_Denon variant
-Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first
+Protocol=Kaseikyo_Denon Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=784050us, Duration=62700us
Send with: IrSender.sendKaseikyo_Denon(0xF2, 0x87, );
rawData[100]:
- -1078550
- +3450,-1750
- + 450,- 400 + 450,- 400 + 500,-1250 + 450,- 400
- + 450,-1300 + 450,- 400 + 450,-1250 + 450,- 450
- + 450,- 400 + 450,-1300 + 450,- 400 + 450,- 400
- + 450,-1300 + 450,-1250 + 450,- 450 + 450,- 400
- + 450,- 400 + 500,- 400 + 450,- 400 + 450,- 450
- + 450,- 400 + 450,-1250 + 450,- 450 + 450,- 400
- + 450,-1250 + 500,-1250 + 450,-1250 + 450,-1300
+ -784050
+ +3450,-1700
+ + 500,- 350 + 500,- 350 + 500,-1250 + 500,- 350
+ + 500,-1250 + 450,- 400 + 500,-1200 + 500,- 400
+ + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400
+ + 450,-1250 + 500,-1250 + 450,- 400 + 500,- 400
+ 450,- 400 + 450,- 400 + 500,- 350 + 500,- 400
- + 450,-1300 + 450,-1250 + 450,-1300 + 450,- 400
- + 450,- 400 + 450,- 450 + 450,- 400 + 450,-1300
- + 450,- 400 + 450,- 400 + 500,- 400 + 450,-1250
- + 500,- 400 + 450,-1250 + 450,- 450 + 450,-1250
+ + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350
+ + 500,-1250 + 500,-1200 + 500,-1250 + 500,-1200
+ + 450,- 400 + 500,- 400 + 500,- 350 + 500,- 400
+ + 500,-1250 + 450,-1250 + 450,-1300 + 450,- 400
+ + 450,- 450 + 450,- 400 + 450,- 400 + 500,-1250
+ + 450,- 400 + 450,- 450 + 450,- 400 + 450,-1250
+ + 450,- 450 + 450,-1250 + 450,- 400 + 500,-1250
+ 450
-Sum: 62700
+Duration=62700us
+
-Send Denon
-Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first
+Send Denon with repeats
+Protocol=Denon Address=0x12, Command=0x87, Raw-Data=0x10F2, 15 bits, LSB first, Gap=782850us, Duration=22100us
Send with: IrSender.sendDenon(0x12, 0x87, );
rawData[32]:
- -1076250
- + 300,- 750 + 300,-1750 + 300,- 750 + 300,- 750
- + 300,-1750 + 300,-1800 + 300,-1750 + 300,-1800
- + 250,- 750 + 300,- 750 + 300,- 750 + 300,- 750
+ -782850
+ + 300,- 750 + 250,-1800 + 300,- 750 + 300,- 750
+ + 300,-1750 + 300,-1750 + 300,-1800 + 300,-1750
+ + 300,- 750 + 300,- 750 + 300,- 750 + 300,- 750
+ 300,-1750 + 300,- 750 + 300,- 750 + 300
-Sum: 22100
+Duration=22100us
+
-Send Denon/Sharp variant
-Protocol=Sharp Address=0x12 Command=0x87 Raw-Data=0x50F2 15 bits LSB first
+Send Denon/Sharp variant with repeats
+Protocol=Sharp Address=0x12, Command=0x87, Raw-Data=0x30F2, 15 bits, LSB first, Gap=726100us, Duration=23150us
Send with: IrSender.sendSharp(0x12, 0x87, );
rawData[32]:
- -1018800
- + 300,- 700 + 300,-1800 + 250,- 750 + 300,- 750
- + 300,-1800 + 250,-1800 + 300,-1750 + 300,-1800
- + 300,- 750 + 250,- 750 + 300,- 750 + 300,- 750
- + 300,-1750 + 300,- 750 + 300,-1800 + 250
-Sum: 23050
+ -726100
+ + 300,- 750 + 300,-1750 + 300,- 750 + 300,- 750
+ + 300,-1750 + 300,-1800 + 300,-1750 + 300,-1800
+ + 300,- 700 + 300,- 750 + 300,- 750 + 300,- 750
+ + 300,-1750 + 300,-1800 + 300,- 750 + 300
+Duration=23150us
+
+
+Send Sony/SIRCS with 7 command and 5 address bits
+Protocol=Sony Address=0x12, Command=0x7, Raw-Data=0x907, 12 bits, LSB first, Gap=727150us, Duration=19800us
+Send with: IrSender.sendSony(0x12, 0x7, 2, 12);
+rawData[26]:
+ -727150
+ +2350,- 600
+ +1250,- 550 +1250,- 550 +1250,- 550 + 600,- 600
+ + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550
+ +1250,- 550 + 650,- 550 + 600,- 600 +1250
+Duration=19800us
+
+
+Send Sony/SIRCS with 7 command and 8 address bits
+Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 15 bits, LSB first, Gap=743050us, Duration=25250us
+Send with: IrSender.sendSony(0xF2, 0x7, 2, 15);
+rawData[32]:
+ -743050
+ +2450,- 550
+ +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550
+ + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550
+ +1250,- 550 + 650,- 550 + 600,- 600 +1250,- 550
+ +1250,- 550 +1250,- 550 +1250
+Duration=25250us
+
+
+Send Sony/SIRCS with 7 command and 13 address bits
+Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 20 bits, LSB first, Gap=746500us, Duration=31250us
+Send with: IrSender.sendSony(0xF2, 0x7, 2, 20);
+rawData[42]:
+ -746500
+ +2450,- 550
+ +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550
+ + 650,- 550 + 600,- 600 + 600,- 600 + 650,- 550
+ +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550
+ +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550
+ + 650,- 550 + 650,- 550 + 650,- 550 + 650
+Duration=31250us
+
+
+Send Samsung 8 bit command and 8 bit address
+Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x7887F2F2, 32 bits, LSB first, Gap=751200us, Duration=65550us
+Send with: IrSender.sendSamsung(0xF2, 0x87, );
+rawData[68]:
+ -751200
+ +4500,-4400
+ + 600,- 500 + 650,-1600 + 650,- 500 + 650,- 450
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 600
+Duration=65550us
+
+
+Send Samsung 16 bit command and address
+Protocol=Samsung Address=0xF2, Command=0xA987, Raw-Data=0xA98700F2, 32 bits, LSB first, Gap=766150us, Duration=60050us
+Send with: IrSender.sendSamsung(0xF2, 0xA987, );
+rawData[68]:
+ -766150
+ +4550,-4350
+ + 650,- 500 + 650,-1600 + 650,- 450 + 650,- 500
+ + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,- 500 + 650,- 450 + 650,- 500 + 650,- 450
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 600,- 550 + 650,- 500 + 600,- 500 + 650,-1600
+ + 600,-1650 + 600,- 500 + 600,- 550 + 650,-1600
+ + 600,- 500 + 600,-1650 + 600,- 500 + 600,-1650
+ + 600
+Duration=60050us
+
+
+Send Samsung48 16 bit command
+Protocol=Samsung48 Address=0xF2, Command=0xA987, Raw-Data=0x56A9, 48 bits, LSB first, Gap=765650us, Duration=87000us
+Send with: IrSender.sendSamsung48(0xF2, 0xA987, );
+rawData[100]:
+ -765650
+ +4450,-4450
+ + 600,- 500 + 650,-1600 + 600,- 550 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,- 500 + 600,- 550 + 600,- 500 + 650,-1600
+ + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 600,- 500 + 600,-1650 + 600,- 500 + 650,-1600
+ + 600,- 550 + 600,-1650 + 600,-1600 + 600,- 550
+ + 600,-1650 + 600,- 500 + 600,-1650 + 600,- 500
+ + 650
+Duration=87000us
+
+
+Send RC5
+Protocol=RC5 Address=0x12, Command=0x7, Raw-Data=0x1487, 13 bits, MSB first, Gap=781750us, Duration=24000us
+Send with: IrSender.sendRC5(0x12, 0x7, );
+rawData[22]:
+ -781750
+ + 950,- 800
+ +1850,-1700 +1850,- 850 + 900,-1750 +1850,- 800
+ + 950,- 850 + 900,- 850 + 950,-1700 + 950,- 850
+ + 950,- 800 + 950
+Duration=24000us
+
+
+Send RC5X with 7.th MSB of command set
+Protocol=RC5 Address=0x12, Command=0x47, Toggle=1, Raw-Data=0xC87, 13 bits, MSB first, Gap=742250us, Duration=24050us
+Send with: IrSender.sendRC5(0x12, 0x47, );
+rawData[22]:
+ -742250
+ +1850,-1700
+ + 950,- 850 +1800,- 850 + 950,-1700 +1850,- 850
+ + 950,- 800 + 950,- 850 + 950,-1700 + 950,- 800
+ + 950,- 850 + 950
+Duration=24050us
+
+
+Send RC6
+Protocol=RC6 Address=0xF2, Command=0x87, Toggle=1, Raw-Data=0x1F287, 20 bits, MSB first, Gap=739800us, Duration=22850us
+Send with: IrSender.sendRC6(0xF2, 0x87, );
+rawData[36]:
+ -739800
+ +2700,- 800
+ + 500,- 850 + 500,- 400 + 500,- 400 +1400,- 850
+ + 500,- 400 + 450,- 400 + 500,- 400 + 500,- 850
+ + 500,- 400 + 950,- 850 +1000,- 800 + 500,- 400
+ + 500,- 400 + 500,- 450 + 900,- 400 + 500,- 400
+ + 500
+Duration=22850us
+
+
+Send RC6A with 14 bit 0x2711 as extra
+Protocol=RC6A Address=0xF2, Command=0x87, Extra=0x2711, Raw-Data=0x2711F287, 35 bits, MSB first, Gap=751050us, Duration=36400us
+Send with: IrSender.sendRC6A(0xF2, 0x87, , 0x2711);
+rawData[60]:
+ -751050
+ +2700,- 800
+ + 500,- 400 + 500,- 450 + 450,- 850 + 500,- 850
+ + 950,- 400 + 950,- 850 + 500,- 400 + 950,- 450
+ + 450,- 450 + 450,- 850 + 500,- 400 + 500,- 400
+ + 950,- 850 + 500,- 400 + 500,- 400 + 950,- 400
+ + 500,- 400 + 500,- 400 + 500,- 400 + 500,- 850
+ + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400
+ + 500,- 450 + 450,- 400 + 950,- 450 + 450,- 450
+ + 450
+Duration=36400us
+
+
+Send MagiQuest, WandId=0x6BCD00F2
+Protocol=MagiQuest Address=0xF2, Command=0x187, Raw-Data=0x6BCD00F2, 56 bits, MSB first, Gap=765950us, Duration=63700us
+Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, );
+rawData[112]:
+ -765950
+ + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
+ + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850
+ + 650,- 500 + 600,- 550 + 350,- 800 + 600,- 550
+ + 300,- 850 + 650,- 500 + 650,- 500 + 650,- 500
+ + 600,- 550 + 300,- 850 + 350,- 800 + 650,- 500
+ + 650,- 500 + 350,- 800 + 650,- 500 + 300,- 850
+ + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
+ + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 550
+ + 600,- 550 + 600,- 550 + 600,- 550 + 300,- 800
+ + 400,- 750 + 650,- 500 + 350,- 850 + 600,- 550
+ + 600,- 550 + 300,- 850 + 300,- 850 + 300,- 850
+ + 300,- 800 + 600,- 550 + 600,- 550 + 650,- 550
+ + 300,- 850 + 300,- 850 + 600,- 550 + 300,- 850
+ + 350,- 800 + 350,- 800 + 600,- 550 + 350
+Duration=63700us
+
+
+Send Lego with 2 channel and with 4 command bits
+Protocol=Lego Address=0x2, Command=0x17, Raw-Data=0x217B, 16 bits, MSB first, Gap=791750us, Duration=10550us
+Send with: IrSender.sendLego(0x2, 0x17, );
+rawData[36]:
+ -791750
+ + 200,-1000
+ + 200,- 500 + 200,- 550 + 200,- 200 + 200,- 500
+ + 200,- 550 + 200,- 500 + 200,- 500 + 200,- 250
+ + 200,- 500 + 200,- 250 + 200,- 200 + 200,- 250
+ + 200,- 200 + 200,- 550 + 200,- 200 + 200,- 250
+ + 200
+Duration=10550us
+
+
+Send Bang&Olufsen / originally with 455 kHz
+- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
+rawData[44]:
+ -748450
+ + 200,-2900
+ + 200,-2900 + 200,-12750 + 250,-2850 + 250,-9100
+ + 200,-5950 + 250,-6000 + 250,-5950 + 200,-2900
+ + 250,-5950 + 200,-9050 + 250,-2900 + 250,-9000
+ + 250,-2900 + 250,-5950 + 250,-5950 + 250,-5950
+ + 200,-9050 + 250,-6000 + 200,-6000 + 200,-12150
+ + 250
+Duration=137200us
+
+- Now try to decode the first 6 entries, which results in rawData 0x0
+Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=748450us, Duration=6400us
+
+- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
+Protocol=Bang&Olufsen Address=0xF2, Command=0x87, Raw-Data=0xF287, 16 bits, MSB first, Gap=12750us, Duration=118050us
+Send with: IrSender.sendBang&Olufsen(0xF2, 0x87, );
+rawData[38]:
+ -12750
+ + 250,-2850
+ + 250,-9100 + 200,-5950 + 250,-6000 + 250,-5950
+ + 200,-2900 + 250,-5950 + 200,-9050 + 250,-2900
+ + 250,-9000 + 250,-2900 + 250,-5950 + 250,-5950
+ + 250,-5950 + 200,-9050 + 250,-6000 + 200,-6000
+ + 200,-12150 + 250
+Duration=118050us
+
+
+Send next protocols with IrSender.write
+
+Send JVC
+Protocol=JVC Address=0xF2, Command=0x87, Raw-Data=0x87F2, 16 bits, LSB first, Gap=804750us, Duration=39400us
+Send with: IrSender.sendJVC(0xF2, 0x87, );
+rawData[36]:
+ -804750
+ +8400,-4150
+ + 550,- 500 + 600,-1500 + 600,- 450 + 600,- 450
+ + 600,-1500 + 600,-1500 + 600,-1500 + 600,-1500
+ + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450
+ + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500
+ + 600
+Duration=39400us
+
+
+Send LG
+Protocol=LG Address=0xF2, Command=0xA987, Raw-Data=0xF2A9872, 28 bits, MSB first, Gap=745550us, Duration=57400us
+Send with: IrSender.sendLG(0xF2, 0xA987, );
+rawData[60]:
+ -745550
+ +9000,-4150
+ + 500,-1550 + 550,-1500 + 550,-1550 + 550,-1500
+ + 550,- 500 + 550,- 500 + 550,-1550 + 500,- 550
+ + 500,-1550 + 550,- 500 + 550,-1550 + 500,- 550
+ + 500,-1550 + 550,- 500 + 550,- 500 + 550,-1550
+ + 500,-1550 + 550,- 500 + 550,- 500 + 550,- 500
+ + 550,- 500 + 550,-1550 + 550,-1500 + 550,-1550
+ + 500,- 550 + 500,- 550 + 500,-1550 + 550,- 500
+ + 550
+Duration=57400us
+
+
+Send Bosewave with no address and 8 command bits
+Protocol=BoseWave Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=762100us, Duration=26750us
+Send with: IrSender.sendBoseWave(0x0, 0x87, );
+rawData[36]:
+ -762100
+ +1050,-1400
+ + 600,-1400 + 600,-1400 + 550,-1400 + 550,- 450
+ + 600,- 400 + 550,- 450 + 500,- 450 + 600,-1400
+ + 550,- 400 + 600,- 400 + 600,- 400 + 600,-1400
+ + 550,-1400 + 600,-1400 + 550,-1400 + 600,- 400
+ + 550
+Duration=26750us
+
+
+Send FAST
+Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=746450us, Duration=28950us
+Send with: IrSender.sendFAST(0x0, 0x87, );
+rawData[36]:
+ -746450
+ +2150,-1050
+ + 550,-1550 + 550,-1500 + 600,-1550 + 550,- 500
+ + 550,- 500 + 550,- 500 + 600,- 450 + 600,-1500
+ + 600,- 450 + 550,- 500 + 600,- 450 + 550,-1550
+ + 600,-1500 + 550,-1550 + 550,-1550 + 550,- 500
+ + 550
+Duration=28950us
+
+
+Force buffer overflow by sending 450 marks and spaces
+Overflow
+Try to increase the "RAW_BUFFER_LENGTH" value of 400 in ../src/UnitTest.cpp
+rawData[400]:
+ -745650
+ + 200,- 450
+ + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 550 + 250,- 500 + 200,- 550 + 200,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 450
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500
+ + 200,- 500 + 250,- 500 + 250,- 550 + 200,- 500
+ + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 550
+ + 250,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450
+ + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500
+ + 250,- 500 + 250,- 500 + 300
+Duration=149500us
+
+ERROR: Unknown protocol
+
+Stop receiver
+Start receiver
+
+address=0x1F3 command=0x98 repeats=2
+
+Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2
+Protocol=NEC Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Gap=923500us, Duration=67850us
+Send with: IrSender.sendNEC(0xF3, 0x98, );
+rawData[68]:
+ -923500
+ +8950,-4400
+ + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600
+ + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500
+ + 650,- 500 + 600,-1600 + 600,-1650 + 600,- 550
+ + 600
+Duration=67850us
+
+
+Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=68750us, Duration=67850us
+Send with: IrSender.sendNEC2(0xF3, 0x98, );
+rawData[68]:
+ -68750
+ +8950,-4350
+ + 650,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1600
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,-1600 + 600,-1650 + 650,- 450
+ + 650
+Duration=67850us
+
+
+Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69400us, Duration=67850us
+Send with: IrSender.sendNEC2(0xF3, 0x98, );
+rawData[68]:
+ -69400
+ +8950,-4400
+ + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ + 650,- 500 + 650,- 500 + 600,-1600 + 650,-1600
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500
+ + 600
+Duration=67850us
+
+
+Send NEC with 16 bit address
+Protocol=NEC Address=0x1F3, Command=0x98, Raw-Data=0x679801F3, 32 bits, LSB first, Gap=765000us, Duration=66650us
+Send with: IrSender.sendNEC(0x1F3, 0x98, );
+rawData[68]:
+ -765000
+ +8950,-4400
+ + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600
+ + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 450 + 650,- 500
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600
+ + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500
+ + 650,- 500 + 650,-1600 + 600,-1650 + 600,- 500
+ + 600
+Duration=66650us
+
+
+Send NEC2 with 16 bit address
+Protocol=NEC Address=0x1F3, Command=0x98, Raw-Data=0x679801F3, 32 bits, LSB first, Gap=764600us, Duration=66750us
+Send with: IrSender.sendNEC(0x1F3, 0x98, );
+rawData[68]:
+ -764600
+ +8950,-4400
+ + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
+ + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450
+ + 650
+Duration=66750us
+
diff --git a/examples/UnitTest/UnitTest_64bit.log b/examples/UnitTest/UnitTest_64bit.log
index 96c2bffea..82e257d33 100644
--- a/examples/UnitTest/UnitTest_64bit.log
+++ b/examples/UnitTest/UnitTest_64bit.log
@@ -1,633 +1,735 @@
-START UnitTest.cpp from Feb 24 2023
-Using library version 4.1.0
-Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 14
-Send IR signals at pin 12
-If you connect debug pin 13 to ground, raw data is always printed
-Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 600 ns, total period is 26 us
+START C:\Users\armin\AppData\Local\Temp\.arduinoIDE-unsaved2025614-8520-1rntouk.pt81h\UnitTest\UnitTest.ino from Jul 14 2025
+Using library version 4.4.2
+Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave, MagiQuest, Universal Pulse Distance Width, Hash at pin 15
+Use ReceiveCompleteCallback
+Receive buffer length is 750
+Send IR signals at pin 4
+If you connect debug pin 16 to ground, raw data is always printed
16000 us is the (minimum) gap, after which the start of a new IR packet is assumed
-100 us are subtracted from all marks and added to all spaces for decoding
+20 us are subtracted from all marks and added to all spaces for decoding
address=0xFFF1 command=0x76
Send NEC with 8 bit address
-Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first
+Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Gap=1047000us Duration=68250us
Send with: IrSender.sendNEC(0xF1, 0x76, );
rawData[68]:
- -1050650
+ -1047000
+9050,-4450
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,-1600
- + 700,- 450 + 650,-1600 + 650,-1650 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,- 450 + 650,-1600 + 650,-1600 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,- 450 + 700,- 450 + 650,-1600
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,-1600
- + 700
-Sum: 68500
+ + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650,- 500 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,-1650 + 650,- 500 + 600,- 500 + 650,-1650
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1650
+ + 600
+Duration=68250us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1067700us Duration=73800us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
rawData[68]:
- -1060200
- +9050,-4400
- + 650,-1600 + 650,- 500 + 650,- 450 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1650 + 650,- 450
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600
- + 650
-Sum: 74050
+ -1067700
+ +9050,-4450
+ + 550,-1650 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,-1650
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,-1650
+ + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600
+ + 650,- 500 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,-1650 + 550,- 550 + 600,- 550 + 600,-1650
+ + 600,- 500 + 600,- 550 + 600,- 500 + 650,-1650
+ + 600
+Duration=73800us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
+Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1067300us Duration=73750us
Send with: IrSender.sendNEC(0xFFF1, 0x76, );
rawData[68]:
- -1060450
- +9050,-4450
- + 650,-1600 + 650,- 500 + 650,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 500
- + 650,-1600 + 650,- 500 + 650,- 500 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650
-Sum: 74150
+ -1067300
+ +9000,-4450
+ + 600,-1650 + 650,- 500 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 650,-1600 + 600,-1650 + 600,-1650
+ + 600,- 550 + 650,-1600 + 600,-1650 + 600,- 500
+ + 650,-1650 + 550,-1650 + 650,-1650 + 550,- 550
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 650,- 500 + 600,- 550 + 650,- 450 + 650,-1650
+ + 550
+Duration=73750us
+
Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats
-Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first
+Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first Gap=1071500us Duration=68500us
Send with: IrSender.sendNEC(0x80, 0x45, );
rawData[68]:
- -1065600
- +9200,-4400
- + 700,- 450 + 700,- 450 + 700,- 500 + 650,- 500
- + 700,- 500 + 650,- 500 + 650,- 550 + 700,-1550
- + 700,-1550 + 700,-1550 + 700,-1550 + 650,-1550
- + 700,-1550 + 700,-1550 + 700,-1550 + 700,- 450
- + 700,-1550 + 650,- 500 + 650,-1600 + 700,- 450
- + 700,- 450 + 700,- 450 + 700,-1550 + 700,- 450
- + 750,- 450 + 700,-1500 + 700,- 450 + 700,-1550
- + 700,-1550 + 700,-1550 + 700,- 450 + 700,-1550
+ -1071500
+ +9100,-4450
+ + 600,- 550 + 650,- 500 + 650,- 550 + 600,- 550
+ + 650,- 500 + 650,- 550 + 600,- 550 + 600,-1600
+ + 650,-1600 + 700,-1550 + 650,-1600 + 550,-1600
+ + 700,-1550 + 650,-1600 + 650,-1600 + 600,- 550
+ + 650,-1550 + 650,- 500 + 650,-1600 + 650,- 500
+ + 700,- 450 + 650,- 500 + 650,-1600 + 650,- 550
+ + 650,- 450 + 700,-1550 + 650,- 500 + 650,-1600
+ + 650,-1600 + 650,-1550 + 650,- 500 + 700,-1550
+ 700
-Sum: 68800
+Duration=68500us
+
Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format)
-Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first
+Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first Gap=1073650us Duration=68450us
Send with: IrSender.sendNEC(0x4, 0x8, );
rawData[68]:
- -1066550
- +9150,-4400
- + 650,- 500 + 650,- 450 + 700,-1600 + 650,- 450
- + 700,- 450 + 650,- 500 + 650,- 450 + 650,- 500
- + 650,-1600 + 700,-1600 + 650,- 450 + 700,-1600
- + 650,-1600 + 700,-1600 + 650,-1600 + 650,-1650
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 700
-Sum: 68700
+ -1073650
+ +9050,-4450
+ + 600,- 550 + 600,- 500 + 650,-1600 + 650,- 500
+ + 600,- 550 + 600,- 550 + 600,- 550 + 550,- 550
+ + 600,-1650 + 600,-1700 + 600,- 500 + 600,-1650
+ + 600,-1650 + 650,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,- 550 + 600,- 500 + 600,-1700
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,- 500
+ + 650,-1650 + 600,-1650 + 600,-1650 + 650,- 500
+ + 600,-1650 + 600,-1650 + 650,-1600 + 650,-1650
+ + 600
+Duration=68450us
+
Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)
-Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first
+Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first Gap=1072150us Duration=55900us
Send with: IrSender.sendOnkyo(0x102, 0x304, );
rawData[68]:
- -1064800
- +9050,-4450
- + 650,- 450 + 650,-1600 + 700,- 450 + 650,- 500
- + 650,- 450 + 650,- 500 + 650,- 500 + 650,- 450
- + 650,-1600 + 700,- 450 + 700,- 450 + 650,- 500
- + 650,- 450 + 650,- 500 + 650,- 450 + 700,- 450
- + 650,- 500 + 650,- 450 + 700,-1600 + 650,- 450
- + 650,- 500 + 650,- 450 + 650,- 500 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,- 500 + 650,- 450
- + 650,- 550 + 650,- 500 + 600,- 500 + 650,- 500
- + 650
-Sum: 56050
+ -1072150
+ +9050,-4400
+ + 600,- 550 + 600,-1650 + 650,- 450 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 500
+ + 650,-1650 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,- 550 + 600,- 550 + 600,-1650 + 600,- 500
+ + 650,- 500 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,- 550 + 600,- 550
+ + 550,- 550 + 600,- 550 + 600,- 500 + 600,- 550
+ + 600
+Duration=55900us
+
Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3)
-Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first
+Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first Gap=1074200us Duration=61500us
Send with: IrSender.sendNEC(0x102, 0x34, );
rawData[68]:
- -1066900
- +9050,-4400
- + 650,- 500 + 650,-1600 + 650,- 500 + 650,- 450
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,- 500
- + 650,-1600 + 650,- 500 + 650,- 450 + 650,- 550
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,- 450
- + 650,- 500 + 650,- 450 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,- 500 + 650,- 450
- + 650,-1600 + 700,-1600 + 600,- 500 + 650,-1650
- + 650,- 450 + 700,- 450 + 650,-1600 + 650,-1600
- + 700
-Sum: 61700
+ -1074200
+ +9050,-4450
+ + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650
+ + 600,- 500 + 600,- 550 + 600,-1650 + 650,-1600
+ + 600
+Duration=61500us
+
-Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants
-Protocol=Panasonic Address=0x10B Command=0xA0 Raw-Data=0xA010B02002 48 bits LSB first
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432
+Protocol=Panasonic Address=0x10B Command=0xA0 Raw-Data=0xA010B02002 48 bits LSB first Gap=1073350us Duration=54650us
Send with: IrSender.sendPanasonic(0x10B, 0xA0, );
rawData[100]:
- -1064700
+ -1073350
+3550,-1650
- + 550,- 350 + 500,-1250 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,- 400 + 450,-1300 + 500,- 350 + 500,- 400
- + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,-1250 + 500,-1250 + 500,- 350 + 500,-1250
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,-1250 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,- 350 + 550,- 350 + 500,- 350 + 550,- 350
- + 500,- 350 + 500,-1250 + 500,- 400 + 500,-1250
- + 500,- 350 + 550,- 350 + 500,- 350 + 550,- 350
- + 500,- 350 + 550,- 350 + 500,- 400 + 500,- 350
- + 500
-Sum: 54750
+ + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 450
+ + 450,- 400 + 500,- 400 + 450,- 400 + 450,- 450
+ + 450,- 400 + 500,- 400 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,-1250 + 500,- 350 + 500,- 400
+ + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500,-1250 + 500,-1250 + 500,- 400 + 450,-1250
+ + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500,-1250 + 450,- 450 + 450,- 400 + 500,- 350
+ + 500,- 400 + 450,- 450 + 450,- 400 + 500,- 400
+ + 450,- 400 + 450,-1300 + 450,- 400 + 500,-1250
+ + 500,- 400 + 450,- 400 + 500,- 400 + 450,- 450
+ + 450,- 400 + 500,- 400 + 450,- 400 + 450,- 450
+ + 450
+Duration=54650us
+
-Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance
- LSB first
-Protocol=Panasonic Address=0x10B Command=0xA0 Raw-Data=0xA010B02002 48 bits LSB first
+Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400
+-LSB first
+Protocol=Panasonic Address=0x10B Command=0xA0 Raw-Data=0xA010B02002 48 bits LSB first Gap=1092300us Duration=53850us
Send with: IrSender.sendPanasonic(0x10B, 0xA0, );
rawData[100]:
- -1082450
- +3550,-1600
- + 550,- 350 + 550,-1150 + 550,- 300 + 600,- 300
- + 550,- 300 + 550,- 300 + 600,- 300 + 550,- 300
- + 550,- 300 + 550,- 350 + 550,- 300 + 550,- 350
- + 550,- 300 + 550,-1200 + 550,- 300 + 550,- 300
- + 550,- 350 + 550,- 300 + 550,- 300 + 550,- 350
- + 550,-1150 + 550,-1200 + 550,- 300 + 550,-1200
- + 550,- 300 + 550,- 300 + 550,- 300 + 600,- 300
- + 550,-1150 + 600,- 300 + 550,- 300 + 550,- 300
- + 550,- 350 + 550,- 300 + 550,- 350 + 550,- 300
- + 550,- 300 + 550,-1200 + 550,- 300 + 550,-1200
- + 550,- 300 + 550,- 300 + 600,- 300 + 550,- 300
- + 550,- 300 + 600,- 300 + 550,- 300 + 550,- 300
- + 550
-Sum: 54200
+ -1092300
+ +3500,-1700
+ + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 400
+ + 450,- 350 + 550,- 350 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,- 350 + 500,- 350 + 500,- 400
+ + 450,- 350 + 550,-1200 + 500,- 350 + 500,- 350
+ + 500,- 400 + 450,- 400 + 500,- 250 + 600,- 350
+ + 500,-1200 + 550,-1200 + 450,- 350 + 550,-1200
+ + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 350
+ + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,-1200 + 500,- 400 + 500,-1200
+ + 500,- 350 + 500,- 350 + 550,- 350 + 450,- 400
+ + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500
+Duration=53850us
- MSB first
-Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B02002 48 bits LSB first
+
+-MSB first
+Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B02002 48 bits LSB first Gap=1084600us Duration=53850us
Send with: IrSender.sendPanasonic(0xB, 0x10, );
rawData[100]:
- -1076300
- +3550,-1600
- + 550,- 350 + 550,-1150 + 550,- 300 + 600,- 300
- + 550,- 300 + 600,- 300 + 550,- 300 + 550,- 300
- + 600,- 300 + 550,- 300 + 550,- 300 + 600,- 300
- + 550,- 300 + 550,-1200 + 550,- 300 + 550,- 300
- + 550,- 350 + 550,- 300 + 550,- 300 + 550,- 350
- + 550,-1150 + 550,-1200 + 550,- 300 + 550,-1200
- + 550,- 300 + 550,- 300 + 550,- 350 + 550,- 300
- + 550,- 350 + 550,- 350 + 550,- 300 + 550,- 300
- + 550,- 350 + 550,- 300 + 550,- 300 + 550,- 350
- + 550,-1150 + 550,- 300 + 600,- 300 + 550,- 300
- + 550,- 300 + 600,- 300 + 550,- 300 + 550,- 300
- + 600,- 300 + 550,-1150 + 550,- 350 + 550,-1150
- + 550
-Sum: 54250
+ -1084600
+ +3500,-1650
+ + 500,- 350 + 550,-1200 + 450,- 400 + 500,- 350
+ + 500,- 350 + 550,- 350 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,- 350 + 500,-1200 + 550,- 350 + 450,- 400
+ + 500,- 350 + 500,- 350 + 550,- 350 + 450,- 400
+ + 500,-1200 + 500,-1200 + 500,- 400 + 500,-1200
+ + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 400
+ + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400
+ + 500,- 350 + 500,- 350 + 500,- 350 + 550,- 350
+ + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 400
+ + 450,- 400 + 500,- 350 + 550,- 300 + 500,- 400
+ + 450,- 400 + 500,-1200 + 500,- 350 + 500,-1250
+ + 500
+Duration=53850us
-Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first
-Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first
-Send with:
+
+Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600
+Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first Gap=1091200us Duration=139400us
+Send on a 32 bit platform with:
uint64_t tRawData[]={0xAFEDCBA987654321, 0x5A};
- IrSender.sendPulseDistanceWidthFromArray(38, 9000, 4350, 650, 1600, 650, 500, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
+ IrSender.sendPulseDistanceWidthFromArray(38, 8950, 4450, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
rawData[148]:
- -1082050
- +9000,-4350
- + 700,-1600 + 650,- 500 + 700,- 500 + 650,- 500
- + 650,- 550 + 650,-1600 + 650,- 550 + 650,- 500
- + 700,-1600 + 650,-1650 + 650,- 500 + 650,- 500
- + 700,- 500 + 650,- 500 + 650,-1650 + 650,- 500
- + 650,-1650 + 650,- 500 + 650,-1650 + 650,- 500
- + 650,- 550 + 650,-1600 + 650,-1650 + 650,- 500
- + 650,-1650 + 650,-1600 + 700,-1600 + 650,- 500
- + 700,- 500 + 650,- 500 + 700,- 500 + 650,-1600
- + 700,-1600 + 650,- 500 + 700,- 500 + 650,-1600
- + 700,- 500 + 650,-1650 + 600,- 550 + 700,-1600
- + 650,-1650 + 650,-1600 + 650,- 550 + 650,-1600
- + 700,- 500 + 650,- 500 + 650,-1650 + 650,-1600
- + 650,-1650 + 650,- 500 + 700,-1600 + 650,-1650
- + 650,- 500 + 650,-1650 + 650,-1600 + 700,-1600
- + 650,-1650 + 650,-1600 + 700,-1600 + 650,-1650
- + 650,- 500 + 650,-1650 + 650,- 500 + 700,-1600
- + 650,- 500 + 700,-1600 + 650,- 550 + 650,-1600
- + 650,-1650 + 650,- 500 + 650,-1650 + 650,- 500
+ -1091200
+ +8950,-4450
+ + 550,-1700 + 600,- 550 + 600,- 550 + 600,- 550
+ + 600,- 600 + 600,-1650 + 600,- 550 + 600,- 600
+ + 550,-1650 + 650,-1650 + 550,- 600 + 600,- 550
+ + 600,- 600 + 550,- 600 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,- 600 + 550,-1700 + 600,- 550
+ + 600,- 600 + 600,-1600 + 650,-1650 + 600,- 550
+ + 600,-1700 + 550,-1650 + 650,-1650 + 550,- 600
+ + 650,- 500 + 600,- 600 + 550,- 600 + 600,-1650
+ + 600,-1650 + 650,- 500 + 600,- 600 + 600,-1650
+ + 600,- 550 + 600,-1650 + 600,- 550 + 650,-1650
+ + 600,-1650 + 650,-1600 + 600,- 600 + 600,-1650
+ + 550,- 600 + 600,- 550 + 600,-1700 + 550,-1700
+ + 600,-1650 + 600,- 550 + 600,-1700 + 550,-1700
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1700
+ + 600,-1650 + 600,-1650 + 600,-1700 + 550,-1700
+ + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1700
+ + 550,- 600 + 600,-1650 + 600,- 550 + 600,-1650
+ + 600,-1700 + 550,- 600 + 600,-1650 + 600,- 550
+ + 600
+Duration=139400us
+
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300
+Protocol=PulseDistance Raw-Data=0xDCBA987654321 52 bits LSB first Gap=1134450us Duration=48650us
+Send on a 32 bit platform with: IrSender.sendPulseDistanceWidth(38, 350, 550, 350, 550, 650, 200, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, , );
+rawData[108]:
+ -1134450
+ + 350,- 550
+ + 350,- 550 + 650,- 200 + 700,- 250 + 700,- 200
+ + 700,- 250 + 350,- 550 + 650,- 200 + 700,- 250
+ + 400,- 550 + 350,- 550 + 650,- 250 + 650,- 250
+ + 700,- 200 + 700,- 250 + 350,- 600 + 650,- 150
+ + 450,- 550 + 650,- 250 + 350,- 550 + 650,- 250
+ + 700,- 150 + 450,- 550 + 350,- 550 + 650,- 250
+ + 350,- 600 + 350,- 550 + 350,- 600 + 600,- 200
+ + 700,- 250 + 700,- 200 + 700,- 200 + 400,- 600
+ + 300,- 550 + 650,- 250 + 700,- 250 + 350,- 550
+ + 650,- 250 + 400,- 550 + 650,- 200 + 450,- 500
+ + 350,- 600 + 300,- 600 + 650,- 200 + 400,- 600
+ + 600,- 200 + 700,- 250 + 350,- 600 + 350,- 550
+ + 350,- 600 + 600,- 200 + 450,- 550 + 350,- 550
+ + 350
+Duration=48650us
+
+
+Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600
+Protocol=PulseDistance Raw-Data=0xDCBA987654321 52 bits LSB first Gap=1104850us Duration=48950us
+Send on a 32 bit platform with: IrSender.sendPulseDistanceWidth(38, 300, 600, 350, 550, 650, 200, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, , );
+rawData[108]:
+ -1104850
+ + 300,- 600
+ + 350,- 550 + 650,- 250 + 650,- 200 + 750,- 200
+ + 700,- 250 + 350,- 550 + 650,- 250 + 700,- 150
+ + 450,- 550 + 350,- 550 + 650,- 200 + 700,- 250
+ + 700,- 250 + 650,- 200 + 400,- 550 + 650,- 250
+ + 400,- 550 + 650,- 250 + 350,- 600 + 600,- 200
+ + 750,- 200 + 400,- 550 + 350,- 550 + 650,- 250
+ + 350,- 550 + 400,- 550 + 350,- 550 + 700,- 150
+ + 700,- 250 + 700,- 250 + 650,- 200 + 400,- 550
+ + 350,- 600 + 650,- 200 + 700,- 250 + 350,- 600
+ + 600,- 200 + 400,- 600 + 650,- 250 + 350,- 550
+ + 350,- 600 + 300,- 550 + 650,- 250 + 400,- 550
+ + 650,- 200 + 700,- 250 + 400,- 550 + 350,- 550
+ + 350,- 550 + 650,- 250 + 350,- 600 + 350,- 550
+ 650
-Sum: 140550
-
-Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first
-Protocol=PulseWidth Raw-Data=0xDCBA987654321 52 bits LSB first
-Send with: IrSender.sendPulseDistanceWidth(38, 400, 550, 750, 150, 400, 500, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, , );
-rawData[106]:
- -1120100
- + 400,- 550
- + 700,- 150 + 450,- 500 + 400,- 550 + 400,- 500
- + 400,- 500 + 700,- 150 + 450,- 550 + 400,- 500
- + 700,- 150 + 800,- 150 + 450,- 500 + 400,- 500
- + 400,- 550 + 350,- 550 + 700,- 200 + 400,- 550
- + 700,- 200 + 400,- 500 + 750,- 200 + 400,- 500
- + 400,- 550 + 700,- 150 + 750,- 200 + 450,- 500
- + 700,- 150 + 750,- 200 + 750,- 150 + 450,- 500
- + 400,- 550 + 400,- 500 + 400,- 500 + 700,- 150
- + 800,- 150 + 450,- 500 + 400,- 500 + 750,- 150
- + 450,- 500 + 700,- 200 + 450,- 500 + 700,- 250
- + 700,- 150 + 800,- 150 + 450,- 500 + 700,- 200
- + 450,- 500 + 400,- 500 + 700,- 200 + 750,- 150
- + 750,- 150 + 450,- 550 + 700,- 200 + 700
-Sum: 48450
-
-Send generic 32 bit PulseWidth 0x87654321 LSB first
-Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
-Send with: IrSender.sendPulseDistanceWidth(38, 1100, 400, 750, 200, 450, 200, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , );
+Duration=48950us
+
+
+Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500
+Protocol=PulseDistance Raw-Data=0x76 7 bits LSB first Gap=1102950us Duration=21150us
+Send on a 32 bit platform with: IrSender.sendPulseDistanceWidth(38, 6050, 500, 500, 1500, 1550, 500, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , );
+rawData[18]:
+ -1102950
+ +6050,- 500
+ +1500,- 500 + 500,-1500 + 550,-1450 +1550,- 500
+ + 500,-1500 + 500,-1500 + 550,-1450 + 550
+Duration=21150us
+
+
+Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600
+Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Gap=1053600us Duration=21200us
+Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
+rawData[26]:
+ -1053600
+ +2450,- 600
+ + 650,- 550 +1250,- 550 +1250,- 600 + 600,- 600
+ +1200,- 600 +1250,- 550 +1250,- 550 +1300,- 500
+ + 650,- 600 + 650,- 550 + 650,- 550 +1250
+Duration=21200us
+
+
+Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300
+Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first Gap=1048400us Duration=24750us
+Send on a 32 bit platform with: IrSender.sendPulseDistanceWidth(38, 1100, 450, 700, 200, 400, 200, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , );
rawData[66]:
- -1090450
- +1100,- 400
- + 700,- 150 + 450,- 200 + 450,- 150 + 450,- 200
- + 400,- 200 + 750,- 150 + 450,- 150 + 450,- 200
- + 700,- 200 + 750,- 200 + 400,- 200 + 400,- 200
- + 450,- 150 + 450,- 150 + 750,- 150 + 450,- 200
- + 750,- 200 + 400,- 200 + 750,- 150 + 450,- 150
- + 450,- 200 + 700,- 200 + 750,- 200 + 400,- 200
- + 750,- 150 + 750,- 200 + 700,- 200 + 450,- 150
- + 450,- 200 + 400,- 200 + 450,- 150 + 750
-Sum: 24900
-
-Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first
-Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
+ -1048400
+ +1100,- 450
+ + 650,- 200 + 400,- 250 + 350,- 250 + 400,- 150
+ + 450,- 200 + 700,- 200 + 400,- 200 + 450,- 200
+ + 700,- 150 + 750,- 250 + 350,- 200 + 400,- 200
+ + 400,- 250 + 400,- 200 + 700,- 200 + 450,- 200
+ + 650,- 200 + 450,- 250 + 650,- 200 + 400,- 250
+ + 400,- 200 + 700,- 150 + 750,- 200 + 400,- 250
+ + 700,- 150 + 700,- 250 + 700,- 250 + 350,- 250
+ + 400,- 200 + 400,- 200 + 400,- 250 + 650
+Duration=24750us
+
+
+Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864
+Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first Gap=1090700us Duration=64700us
Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, );
rawData[112]:
- -1070250
- + 400,- 800 + 400,- 750 + 450,- 800 + 400,- 750
- + 400,- 800 + 400,- 750 + 400,- 800 + 400,- 750
- + 700,- 500 + 650,- 500 + 400,- 800 + 650,- 500
- + 400,- 800 + 650,- 500 + 700,- 500 + 650,- 500
- + 700,- 450 + 450,- 750 + 400,- 750 + 700,- 500
- + 700,- 450 + 400,- 800 + 700,- 450 + 700,- 500
- + 700,- 500 + 650,- 500 + 700,- 450 + 700,- 500
- + 700,- 450 + 700,- 500 + 700,- 450 + 400,- 800
- + 350,- 800 + 400,- 800 + 400,- 750 + 400,- 800
- + 400,- 750 + 400,- 800 + 400,- 750 + 700,- 450
- + 450,- 750 + 700,- 450 + 700,- 500 + 700,- 450
- + 400,- 800 + 650,- 500 + 700,- 500 + 400,- 750
- + 400,- 800 + 400,- 750 + 450,- 750 + 700,- 450
- + 700,- 500 + 400,- 750 + 400,- 800 + 700
-Sum: 65350
+ -1090700
+ + 300,- 850 + 350,- 800 + 350,- 800 + 350,- 850
+ + 350,- 800 + 350,- 800 + 350,- 850 + 350,- 800
+ + 650,- 500 + 650,- 550 + 300,- 850 + 650,- 500
+ + 300,- 900 + 600,- 550 + 600,- 550 + 650,- 550
+ + 600,- 550 + 300,- 850 + 350,- 850 + 600,- 550
+ + 600,- 550 + 350,- 800 + 650,- 550 + 600,- 550
+ + 650,- 500 + 650,- 550 + 600,- 550 + 600,- 550
+ + 650,- 550 + 600,- 550 + 600,- 550 + 350,- 850
+ + 300,- 850 + 300,- 850 + 350,- 850 + 300,- 850
+ + 300,- 850 + 300,- 850 + 350,- 800 + 650,- 550
+ + 300,- 850 + 600,- 550 + 650,- 550 + 600,- 550
+ + 350,- 800 + 650,- 550 + 600,- 550 + 350,- 800
+ + 350,- 850 + 300,- 850 + 350,- 800 + 650,- 500
+ + 650,- 550 + 300,- 850 + 350,- 800 + 650
+Duration=64700us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first
+Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Gap=1113450us Duration=77150us
Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, );
rawData[68]:
- -1086400
- +9050,-4400
- + 700,-1600 + 650,- 450 + 700,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,- 450 + 700,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,- 500
+ -1113450
+ +9000,-4450
+ + 650,-1600 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 650,-1600
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,-1600 + 600,-1650 + 650,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ 650
-Sum: 77500
+Duration=77150us
+
Send Apple
-Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first
+Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Gap=1065600us Duration=72650us
Send with: IrSender.sendApple(0xF1, 0x76, );
rawData[68]:
- -1059500
- +9050,-4400
- + 700,- 500 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,-1600
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,- 450 + 700,- 450 + 700,- 450 + 650,-1600
- + 650,- 500 + 650,-1600 + 650,-1600 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,- 450 + 650,- 500 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
+ -1065600
+ +9000,-4450
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650
+ + 650,- 450 + 600,-1650 + 650,-1600 + 600,-1700
+ + 550,-1650 + 600,-1700 + 600,-1600 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,-1650 + 550,-1650 + 650,-1650 + 550,- 550
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ 600
-Sum: 73000
+Duration=72650us
+
Send Panasonic
-Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF102002 48 bits LSB first
+Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF102002 48 bits LSB first Gap=1065700us Duration=65000us
Send with: IrSender.sendPanasonic(0xFF1, 0x76, );
rawData[100]:
- -1059200
+ -1065700
+3500,-1700
- + 500,- 350 + 500,-1250 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,-1250 + 500,- 350 + 500,- 400
- + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400
- + 500,-1250 + 500,- 350 + 500,- 400 + 450,- 400
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,- 400 + 500,-1250 + 500,-1250 + 500,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 400
- + 500,-1250 + 500,- 350 + 500,- 400 + 500,-1250
- + 500,-1250 + 500,- 400 + 500,- 350 + 500,-1250
- + 500
-Sum: 65200
+ + 500,- 400 + 450,-1250 + 500,- 400 + 500,- 400
+ + 450,- 400 + 500,- 400 + 450,- 400 + 500,- 400
+ + 450,- 400 + 500,- 400 + 450,- 400 + 550,- 350
+ + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 400
+ + 500,- 350 + 500,- 400 + 500,- 400 + 450,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,-1300
+ + 450,-1300 + 450,-1250 + 500,-1250 + 500,-1250
+ + 450,- 450 + 450,-1250 + 500,-1250 + 500,- 350
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,- 450
+ + 450,-1250 + 500,- 400 + 450,- 400 + 500,-1250
+ + 500,-1250 + 500,- 350 + 500,- 400 + 450,-1300
+ + 450
+Duration=65000us
+
Send Kaseikyo with 0x4711 as Vendor ID
-Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF134711 48 bits LSB first
+Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF134711 48 bits LSB first Gap=1091050us Duration=70250us
Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711);
rawData[100]:
- -1079950
+ -1091050
+3550,-1650
- + 500,-1250 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,-1250 + 500,- 350 + 550,- 350 + 500,- 400
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,-1250 + 500,- 400
- + 500,-1250 + 500,-1250 + 500,- 350 + 500,- 400
- + 500,-1250 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,-1250 + 500,-1250 + 500,-1250 + 550,-1200
- + 550,- 350 + 500,-1250 + 500,-1250 + 500,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 550,- 350
- + 500,- 350 + 500,-1250 + 550,- 350 + 500,-1250
- + 500,-1250 + 500,- 350 + 500,- 400 + 500,-1250
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400
+ + 450,-1300 + 450,- 400 + 500,- 350 + 500,- 400
+ + 500,-1250 + 450,-1300 + 450,-1300 + 450,- 400
+ + 500,- 400 + 450,- 400 + 450,-1300 + 450,- 400
+ + 500,-1250 + 500,-1250 + 500,- 400 + 450,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 350
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,-1300
+ + 450,-1300 + 450,-1250 + 500,-1250 + 500,-1250
+ + 450,- 450 + 450,-1250 + 500,-1250 + 500,- 350
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,- 450
+ + 450,- 400 + 500,-1250 + 450,- 450 + 450,-1250
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250
+ 500
-Sum: 70500
+Duration=70250us
+
Send Kaseikyo_Denon variant
-Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF103254 48 bits LSB first
+Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF103254 48 bits LSB first Gap=1089850us Duration=68450us
Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, );
rawData[100]:
- -1080650
- +3550,-1650
- + 550,- 350 + 500,- 350 + 550,-1200 + 550,- 350
- + 500,-1250 + 500,- 350 + 550,-1200 + 500,- 400
- + 500,- 350 + 500,-1250 + 550,- 350 + 500,- 350
- + 550,-1200 + 550,-1200 + 550,- 350 + 500,- 350
- + 550,- 350 + 500,- 350 + 550,- 350 + 500,- 350
- + 550,-1200 + 550,- 350 + 500,- 350 + 550,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,- 350 + 500,-1250 + 500,-1250 + 500,- 400
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 350
- + 500,-1250 + 550,- 350 + 500,- 350 + 550,-1250
- + 450,-1300 + 500,- 350 + 500,- 400 + 500,-1250
+ -1089850
+ +3500,-1650
+ + 500,- 400 + 500,- 400 + 450,-1250 + 500,- 400
+ + 500,-1250 + 450,- 400 + 500,-1250 + 450,- 450
+ + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 400
+ + 450,-1300 + 500,-1200 + 500,- 400 + 450,- 400
+ + 500,- 400 + 450,- 400 + 500,- 400 + 450,- 400
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400
+ + 450,-1300 + 450,-1250 + 500,-1250 + 500,-1250
+ + 500,-1250 + 450,-1300 + 450,-1300 + 450,-1250
+ + 550,- 350 + 450,-1250 + 500,-1250 + 500,- 400
+ + 450,-1300 + 450,-1300 + 450,-1250 + 450,- 450
+ + 450,-1250 + 500,- 400 + 450,- 450 + 450,-1250
+ + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250
+ 500
-Sum: 68750
+Duration=68450us
+
Send Denon
-Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first
+Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Gap=1089050us Duration=23400us
Send with: IrSender.sendDenon(0x11, 0x76, );
rawData[32]:
- -1078400
- + 350,-1750 + 350,- 700 + 350,- 700 + 350,- 700
- + 350,-1750 + 350,- 700 + 300,-1800 + 350,-1750
- + 350,- 700 + 350,-1750 + 350,-1750 + 350,-1750
- + 350,- 700 + 350,- 700 + 350,- 700 + 350
-Sum: 23450
+ -1089050
+ + 350,-1750 + 300,- 750 + 300,- 750 + 300,- 750
+ + 300,-1800 + 300,- 750 + 300,-1800 + 300,-1800
+ + 300,- 750 + 300,-1800 + 300,-1750 + 350,-1750
+ + 300,- 750 + 350,- 750 + 300,- 750 + 300
+Duration=23400us
+
Send Denon/Sharp variant
-Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first
-Send with: IrSender.sendSharp(0x11, 0x76, );
+Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x2ED1 15 bits LSB first Gap=1034900us Duration=24450us
+Send with: IrSender.sendDenon(0x11, 0x76, );
rawData[32]:
- -1023500
- + 350,-1750 + 350,- 700 + 350,- 700 + 350,- 700
- + 350,-1750 + 350,- 700 + 350,-1750 + 350,-1750
- + 350,- 700 + 350,-1750 + 350,-1750 + 350,-1750
- + 350,- 700 + 300,- 750 + 350,-1750 + 350
-Sum: 24500
+ -1034900
+ + 300,-1800 + 300,- 750 + 300,- 750 + 300,- 750
+ + 300,-1800 + 300,- 750 + 300,-1800 + 300,-1800
+ + 300,- 750 + 300,-1800 + 300,-1800 + 300,-1750
+ + 350,- 700 + 300,-1800 + 300,- 750 + 350
+Duration=24450us
+
Send Sony/SIRCS with 7 command and 5 address bits
-Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first
+Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Gap=1037050us Duration=21150us
Send with: IrSender.sendSony(0x11, 0x76, 2, 12);
rawData[26]:
- -1025750
- +2500,- 500
- + 700,- 500 +1300,- 650 +1250,- 550 + 700,- 500
- +1300,- 500 +1300,- 500 +1300,- 550 +1300,- 500
- + 700,- 500 + 700,- 500 + 700,- 550 +1250
-Sum: 21300
+ -1037050
+ +2400,- 600
+ + 650,- 550 +1250,- 550 +1300,- 550 + 600,- 600
+ +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550
+ + 650,- 600 + 650,- 550 + 650,- 550 +1250
+Duration=21150us
+
Send Sony/SIRCS with 7 command and 8 address bits
-Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first
+Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Gap=1046850us Duration=26600us
Send with: IrSender.sendSony(0xF1, 0x76, 2, 15);
rawData[32]:
- -1037600
- +2500,- 550
- + 650,- 550 +1300,- 500 +1300,- 500 + 700,- 500
- +1300,- 550 +1250,- 550 +1300,- 500 +1300,- 500
- + 700,- 500 + 700,- 550 + 650,- 550 +1300,- 500
- +1300,- 550 +1300,- 500 +1300
-Sum: 26700
+ -1046850
+ +2450,- 550
+ + 650,- 550 +1250,- 550 +1250,- 600 + 600,- 600
+ +1250,- 550 +1250,- 550 +1250,- 600 +1200,- 550
+ + 650,- 600 + 650,- 550 + 650,- 600 +1200,- 550
+ +1250,- 600 +1250,- 550 +1250
+Duration=26600us
+
Send Sony/SIRCS with 7 command and 13 address bits
-Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first
+Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Gap=1057450us Duration=35700us
Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20);
rawData[42]:
- -1041100
- +2500,- 500
- + 700,- 550 +1300,- 500 +1300,- 500 + 700,- 550
- +1250,- 550 +1300,- 500 +1300,- 550 +1300,- 500
- + 700,- 500 + 700,- 500 + 700,- 500 +1300,- 550
- +1300,- 500 +1300,- 500 +1300,- 500 +1300,- 550
- +1300,- 500 +1300,- 500 +1300,- 550 +1250
-Sum: 35750
-
-Send Samsung 8 bit command
-Protocol=Samsung Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first
-Send with: IrSender.sendSamsung(0xFFF1, 0x76, );
+ -1057450
+ +2450,- 600
+ + 650,- 550 +1200,- 600 +1250,- 550 + 650,- 550
+ +1250,- 600 +1250,- 550 +1250,- 550 +1250,- 550
+ + 650,- 600 + 650,- 550 + 650,- 550 +1250,- 550
+ +1250,- 600 +1250,- 550 +1250,- 550 +1250,- 550
+ +1250,- 550 +1250,- 600 +1200,- 600 +1250
+Duration=35700us
+
+
+Send Samsung 8 bit command and 8 bit address
+Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first Gap=1056800us Duration=65950us
+Send with: IrSender.sendSamsung(0xF1, 0x76, );
rawData[68]:
- -1044850
- +4550,-4400
- + 700,-1600 + 650,- 450 + 700,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,- 450 + 700,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,-1600
- + 650
-Sum: 69600
+ -1056800
+ +4550,-4450
+ + 550,-1700 + 600,- 500 + 600,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,- 550 + 550,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 600,-1650 + 650,-1600 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+ + 600
+Duration=65950us
+
-Send Samsung 16 bit command
-Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first
+Send Samsung 16 bit command and address
+Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Gap=1068600us Duration=69300us
Send with: IrSender.sendSamsung(0xFFF1, 0x9876, );
rawData[68]:
- -1061000
- +4600,-4400
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,-1550 + 700,-1600 + 650,-1600 + 650,-1600
- + 650,-1600 + 700,-1600 + 650,-1600 + 650,-1600
- + 650,-1600 + 700,-1600 + 650,-1600 + 650,-1600
- + 650,- 500 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,-1600 + 650,- 500 + 650,- 450 + 700,-1600
- + 650
-Sum: 69650
+ -1068600
+ +4550,-4450
+ + 600,-1650 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 550,-1650 + 650,-1650 + 550,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1650
+ + 600,-1650 + 600,- 550 + 600,- 500 + 600,-1650
+ + 600
+Duration=69300us
+
Send Samsung48 16 bit command
-Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0xFFFFFFFF8976FFF1 48 bits LSB first
+Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0xFFFFFFFF8976FFF1 48 bits LSB first Gap=1066850us Duration=96400us
Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, );
rawData[100]:
- -1066350
+ -1066850
+4550,-4400
- + 650,-1650 + 600,- 500 + 700,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,-1600
- + 600,-1650 + 650,-1600 + 650,-1600 + 700,-1600
- + 600,-1650 + 650,-1600 + 650,-1600 + 700,-1550
- + 700,- 450 + 650,-1600 + 700,-1600 + 600,- 500
- + 650,-1600 + 700,-1600 + 650,-1600 + 650,- 500
- + 650,-1600 + 650,- 500 + 650,- 500 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600
- + 650,-1600 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,-1600 + 650,-1600 + 650,-1650 + 650,- 450
- + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500
+ + 650,-1650 + 550,- 550 + 600,- 550 + 600,- 500
+ + 600,-1650 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,-1650 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,-1650 + 650,-1600 + 600,-1650 + 650,-1600
+ + 600,- 550 + 600,-1650 + 650,-1600 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 550,-1650 + 650,- 500 + 600,- 550 + 600,-1650
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1650
+ + 600,- 550 + 550,- 550 + 600,- 550 + 600,-1650
+ + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,- 500 + 650,-1650 + 550,-1650 + 650,- 500
+ 650
-Sum: 96750
+Duration=96400us
+
Send RC5
-Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first
+Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Gap=1089700us Duration=23300us
Send with: IrSender.sendRC5(0x11, 0x36, );
rawData[20]:
- -1079150
- +1000,- 800
- +1900,-1650 +1900,- 800 +1000,- 800 +1000,-1700
- +1000,- 800 +1000,- 750 +1900,-1700 +1000,- 800
- +1900
-Sum: 23400
+ -1089700
+ + 900,- 850
+ +1850,-1750 +1850,- 850 + 900,- 850 + 950,-1750
+ + 950,- 850 + 950,- 850 +1800,-1750 + 950,- 850
+ +1850
+Duration=23300us
+
Send RC5X with 7.th MSB of command set
-Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first
+Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Gap=1047250us Duration=23350us
Send with: IrSender.sendRC5(0x11, 0x76, );
rawData[20]:
- -1035450
- +1900,-1700
- +1000,- 800 +1900,- 750 +1000,- 800 +1000,-1700
- +1000,- 800 +1000,- 800 +1900,-1650 +1000,- 800
- +1900
-Sum: 23400
+ -1047250
+ +1850,-1750
+ + 950,- 850 +1850,- 850 + 900,- 900 + 900,-1750
+ + 950,- 850 + 950,- 850 +1800,-1750 +1000,- 800
+ +1850
+Duration=23350us
+
Send RC6
-Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first
+Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Gap=1043200us Duration=23400us
Send with: IrSender.sendRC6(0xF1, 0x76, );
rawData[36]:
- -1032650
+ -1043200
+ +2700,- 850
+ + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850
+ +1400,- 400 + 500,- 400 + 500,- 400 + 500,- 850
+ + 500,- 400 + 500,- 400 + 950,- 850 + 950,- 400
+ + 500,- 400 + 500,- 850 + 950,- 400 + 500,- 850
+ + 500
+Duration=23400us
+
+
+Send RC6A with 14 bit 0x2711 as extra
+Protocol=RC6A Address=0xF1 Command=0x76 Extra=0x2711 Toggle=1 Raw-Data=0xA711F176 35 bits MSB first Gap=1067100us Duration=36900us
+Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711);
+rawData[58]:
+ -1067100
+2750,- 800
- + 550,- 800 + 550,- 350 + 550,- 350 + 550,- 800
- +1450,- 350 + 550,- 350 + 550,- 350 + 550,- 800
- + 550,- 350 + 550,- 350 +1000,- 800 +1000,- 350
- + 550,- 350 + 550,- 800 +1000,- 350 + 550,- 800
- + 550
-Sum: 23450
+ + 500,- 400 + 500,- 350 + 600,- 800 +1400,-1300
+ + 950,- 850 + 500,- 400 + 950,- 400 + 500,- 400
+ + 500,- 850 + 500,- 400 + 500,- 400 + 950,- 850
+ + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 400
+ + 500,- 400 + 500,- 400 + 500,- 850 + 500,- 400
+ + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400
+ + 500,- 850 + 950,- 400 + 500,- 850 + 500
+Duration=36900us
+
Send Bang&Olufsen
- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled
-- Now print raw data and try to decode the first 6 entries, which results in rawData 0x0!
-rawData[36]:
- -1032400
- + 300,-2850
- + 250,-2850 + 250,-15200 + 300,-2850 + 250,-9000
- + 300,-5950 + 250,-5950 + 250,-5900 + 300,-2850
- + 250,-5950 + 250,-9050 + 250,-2850 + 250,-9000
- + 300,-2850 + 250,-5950 + 250,-5950 + 250,-5950
+rawData[44]:
+ -1066350
+ + 250,-2900
+ + 250,-2900 + 250,-12750 + 250,-2850 + 250,-9150
+ + 250,-6000 + 250,-6050 + 250,-6000 + 250,-2850
+ + 250,-6050 + 250,-6000 + 250,-9150 + 250,-2850
+ + 250,-9150 + 250,-6000 + 250,-6000 + 250,-2900
+ + 250,-9150 + 250,-6000 + 250,-2900 + 250,-12250
+ 250
-Sum: 105700
-Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first
+Duration=135350us
+
+- Now try to decode the first 6 entries, which results in rawData 0x0
+Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first Gap=1066350us Duration=6550us
- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode
-Protocol=Bang&Olufsen Address=0xF2 Command=0x87 Raw-Data=0xF287 16 bits MSB first
-Send with: IrSender.sendBang&Olufsen(0xF2, 0x87, );
+Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Gap=12750us Duration=116050us
+Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, );
rawData[38]:
- -15200
- + 300,-2850
- + 250,-9000 + 300,-5950 + 250,-5950 + 250,-5900
- + 300,-2850 + 250,-5950 + 250,-9050 + 250,-2850
- + 250,-9000 + 300,-2850 + 250,-5950 + 250,-5950
- + 250,-5950 + 250,-9050 + 250,-5900 + 300,-5950
- + 250,-12100 + 300
-Sum: 118100
+ -12750
+ + 250,-2850
+ + 250,-9150 + 250,-6000 + 250,-6050 + 250,-6000
+ + 250,-2850 + 250,-6050 + 250,-6000 + 250,-9150
+ + 250,-2850 + 250,-9150 + 250,-6000 + 250,-6000
+ + 250,-2900 + 250,-9150 + 250,-6000 + 250,-2900
+ + 250,-12250 + 250
+Duration=116050us
+
Send MagiQuest
-Protocol=MagiQuest Address=0xF2 Command=0x187 Raw-Data=0x6BCD00F2 56 bits MSB first
-Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, );
+Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Gap=1104750us Duration=64450us
+Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, );
rawData[112]:
- -1088750
- + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
- + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850
- + 600,- 550 + 600,- 550 + 350,- 750 + 650,- 550
- + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550
- + 600,- 550 + 350,- 800 + 350,- 750 + 650,- 500
- + 650,- 500 + 350,- 800 + 650,- 500 + 350,- 800
- + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800
- + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 500
- + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800
- + 350,- 800 + 650,- 500 + 350,- 850 + 600,- 550
- + 600,- 550 + 350,- 800 + 300,- 800 + 350,- 800
- + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 550
- + 350,- 800 + 300,- 800 + 650,- 500 + 350,- 800
- + 350,- 800 + 350,- 800 + 650,- 500 + 350
-Sum: 63600
+ -1104750
+ + 350,- 850 + 300,- 850 + 300,- 850 + 300,- 850
+ + 350,- 800 + 350,- 800 + 350,- 850 + 300,- 850
+ + 600,- 550 + 600,- 550 + 350,- 800 + 650,- 550
+ + 350,- 800 + 600,- 550 + 600,- 550 + 650,- 500
+ + 650,- 550 + 300,- 850 + 300,- 850 + 600,- 550
+ + 600,- 550 + 350,- 800 + 650,- 550 + 600,- 550
+ + 650,- 500 + 650,- 550 + 600,- 550 + 600,- 550
+ + 600,- 550 + 600,- 550 + 600,- 550 + 650,- 500
+ + 650,- 550 + 600,- 550 + 650,- 500 + 350,- 850
+ + 300,- 850 + 300,- 850 + 600,- 550 + 350,- 800
+ + 350,- 800 + 650,- 550 + 600,- 550 + 600,- 550
+ + 350,- 850 + 600,- 550 + 600,- 550 + 300,- 850
+ + 350,- 800 + 350,- 800 + 650,- 500 + 650,- 550
+ + 350,- 800 + 650,- 500 + 650,- 550 + 600
+Duration=64450us
+
Send next protocols with IrSender.write
Send JVC
-Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first
+Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first Gap=1114750us Duration=40800us
Send with: IrSender.sendJVC(0xF1, 0x76, );
rawData[36]:
- -1040750
+ -1114750
+8500,-4150
- + 650,-1500 + 650,- 400 + 650,- 450 + 600,- 450
- + 650,-1500 + 600,-1500 + 650,-1500 + 600,-1550
- + 600,- 450 + 650,-1500 + 650,-1450 + 650,- 450
- + 650,-1450 + 650,-1500 + 650,-1500 + 600,- 450
- + 650
-Sum: 41050
+ + 550,-1550 + 600,- 500 + 550,- 500 + 600,- 450
+ + 600,-1500 + 600,-1550 + 550,-1550 + 600,-1550
+ + 550,- 500 + 600,-1550 + 550,-1550 + 550,- 500
+ + 550,-1550 + 600,-1550 + 550,-1550 + 550,- 500
+ + 600
+Duration=40800us
+
Send LG
-Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first
+Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first Gap=1053400us Duration=60000us
Send with: IrSender.sendLG(0xF1, 0x9876, );
rawData[60]:
- -1059650
- +9100,-4100
- + 650,-1500 + 600,-1500 + 600,-1500 + 600,-1500
- + 600,- 500 + 600,- 450 + 600,- 450 + 650,-1500
- + 600,-1500 + 600,- 450 + 600,- 500 + 600,-1500
- + 600,-1500 + 600,- 500 + 600,- 450 + 600,- 450
- + 650,- 450 + 600,-1500 + 600,-1500 + 600,-1500
- + 650,- 450 + 600,-1500 + 600,-1500 + 600,- 500
- + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 500
- + 600
-Sum: 60450
+ -1053400
+ +9050,-4150
+ + 550,-1550 + 550,-1550 + 550,-1550 + 550,-1550
+ + 550,- 500 + 550,- 500 + 550,- 550 + 550,-1500
+ + 600,-1500 + 550,- 500 + 550,- 550 + 550,-1500
+ + 550,-1550 + 550,- 500 + 600,- 450 + 600,- 500
+ + 550,- 500 + 550,-1550 + 550,-1550 + 550,-1550
+ + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
+ + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
+ + 550
+Duration=60000us
+
Send Bosewave with no address and 8 command bits
-Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
+Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Gap=1068550us Duration=27050us
Send with: IrSender.sendBoseWave(0x0, 0x76, );
rawData[36]:
- -1050250
- +1100,-1400
- + 600,- 400 + 600,-1400 + 600,-1400 + 600,- 400
- + 600,-1400 + 600,-1400 + 650,-1400 + 600,- 400
+ -1068550
+ +1050,-1450
+ + 600,- 400 + 550,-1450 + 550,-1450 + 600,- 400
+ + 550,-1450 + 550,-1400 + 600,-1400 + 600,- 400
+ 600,-1400 + 600,- 400 + 600,- 400 + 600,-1400
+ 600,- 400 + 600,- 400 + 600,- 400 + 600,-1400
+ 600
-Sum: 27150
+Duration=27050us
+
Send FAST
-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 Gap=1053550us Duration=29200us
Send with: IrSender.sendFAST(0x0, 0x76, );
rawData[36]:
- -1041350
- +2200,-1000
- + 650,- 400 + 650,-1500 + 650,-1500 + 600,- 450
- + 650,-1500 + 650,-1500 + 600,-1500 + 650,- 450
- + 600,-1500 + 650,- 450 + 600,- 450 + 650,-1500
- + 600,- 450 + 650,- 450 + 600,- 450 + 650,-1500
- + 600
-Sum: 29450
+ -1053550
+ +2150,-1050
+ + 550,- 500 + 550,-1550 + 600,-1550 + 550,- 500
+ + 550,-1600 + 550,-1550 + 550,-1550 + 600,- 450
+ + 600,-1500 + 600,- 500 + 550,- 500 + 600,-1550
+ + 550,- 500 + 600,- 450 + 600,- 500 + 550,-1550
+ + 550
+Duration=29200us
+
Force buffer overflow by sending 280 marks and spaces
Overflow
@@ -663,148 +765,338 @@ rawData[200]:
Sum: 77050
ERROR: Unknown protocol
+Stop receiver
+Start receiver
address=0xF2 command=0x87
Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1275750us Duration=68200us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -3276750
- +8900,-4450
- + 600,- 500 + 650,-1600 + 600,- 550 + 600,- 500
- + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1650
- + 600,-1600 + 600,- 550 + 600,-1600 + 650,-1600
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
- + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1600
- + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,- 550
+ -1275750
+ +9000,-4450
+ + 650,- 500 + 600,-1650 + 600,- 550 + 600,- 550
+ + 550,-1650 + 650,-1650 + 550,-1650 + 650,-1650
+ + 550,-1650 + 650,- 500 + 600,-1650 + 600,-1650
+ + 650,- 450 + 650,- 500 + 600,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,-1650
+ + 550,-1650 + 650,-1650 + 550,-1650 + 650,- 500
+ 600
-Sum: 67850
+Duration=68200us
-Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first
+
+Protocol=NEC2 Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Repeat Gap=65700us Duration=68200us
Send with: IrSender.sendNEC2(0xF2, 0x87, );
rawData[68]:
- -65900
- +8900,-4450
- + 600,- 500 + 600,-1650 + 600,- 500 + 600,- 550
- + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650
- + 600,-1650 + 600,- 500 + 600,-1650 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 550 + 600,- 500
- + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550
- + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
- + 600,- 500 + 600,- 550 + 600,- 500 + 650,-1600
- + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 550
- + 600
-Sum: 67800
+ -65700
+ +9000,-4450
+ + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,- 500 + 650,-1650 + 600,-1650
+ + 600,- 550 + 550,- 550 + 600,- 550 + 600,- 500
+ + 600,-1650 + 650,-1600 + 600,-1650 + 600,- 550
+ + 600,- 500 + 650,- 550 + 550,- 550 + 600,-1650
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650
+Duration=68200us
+
Send NEC with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1067650us Duration=68200us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -1060000
- +9100,-4400
- + 650,- 450 + 700,-1600 + 650,- 450 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,- 500 + 650,-1600 + 650,-1600
- + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500
- + 650,-1600 + 650,-1600 + 650,-1600 + 700,- 450
- + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,-1600
- + 700,-1550 + 700,-1600 + 650,-1600 + 650,- 500
- + 650
-Sum: 68450
+ -1067650
+ +9000,-4450
+ + 600,- 550 + 600,-1650 + 600,- 550 + 600,- 500
+ + 650,-1650 + 550,-1650 + 650,-1600 + 600,-1650
+ + 650,-1600 + 600,- 550 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 550,- 550 + 600,- 550 + 600,- 500 + 600,-1650
+ + 600,- 550 + 600,- 550 + 600,- 550 + 550,-1650
+ + 650,-1650 + 550,-1650 + 650,-1650 + 550,- 550
+ + 600
+Duration=68200us
+
Send NEC2 with 16 bit address
-Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first
+Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1066900us Duration=68200us
Send with: IrSender.sendNEC(0xF2, 0x87, );
rawData[68]:
- -1060100
- +9050,-4400
- + 700,- 450 + 650,-1600 + 650,- 500 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,-1600
- + 700,-1600 + 650,- 450 + 700,-1600 + 650,-1600
- + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 450
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 650,- 500 + 650,- 450 + 650,-1600
- + 700,-1600 + 600,-1650 + 650,-1600 + 650,- 500
- + 650
-Sum: 68450
+ -1066900
+ +9000,-4450
+ + 650,- 500 + 600,-1650 + 600,- 550 + 550,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,- 500 + 650,-1650 + 600,-1650
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,- 550 + 600,- 550 + 600,- 500 + 650,-1650
+ + 550,- 550 + 600,- 550 + 600,- 500 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600
+Duration=68200us
+
Send Onkyo (NEC with 16 bit command)
-Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first
+Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Gap=1068400us Duration=62600us
Send with: IrSender.sendOnkyo(0xF2, 0x8887, );
rawData[68]:
- -1060700
- +9100,-4400
- + 650,- 450 + 700,-1600 + 650,- 450 + 700,- 450
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,- 450
- + 700,- 450 + 650,- 500 + 650,- 450 + 650,- 500
- + 650,-1600 + 650,-1600 + 700,-1550 + 700,- 450
- + 650,- 500 + 650,- 500 + 650,- 450 + 650,-1600
- + 700,- 450 + 650,- 500 + 650,- 450 + 650,-1650
- + 650,- 500 + 650,- 450 + 700,- 450 + 650,-1600
- + 650
-Sum: 62800
+ -1068400
+ +9000,-4450
+ + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 550
+ + 550,-1650 + 650,-1650 + 550,-1650 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+ + 600
+Duration=62600us
+
Send Apple
-Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first
+Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Gap=1067150us Duration=71550us
Send with: IrSender.sendApple(0xF2, 0x87, );
rawData[68]:
- -1059150
- +9050,-4400
- + 650,- 500 + 650,-1600 + 650,-1600 + 700,-1600
- + 650,- 450 + 650,-1600 + 700,-1600 + 650,-1600
- + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450
- + 700,- 450 + 650,- 500 + 650,- 450 + 650,-1600
- + 700,-1600 + 650,-1600 + 650,-1600 + 650,- 500
- + 650,- 450 + 700,- 450 + 650,- 500 + 650,-1600
- + 650,- 500 + 600,-1650 + 650,- 500 + 650,- 450
- + 650,-1600 + 650,-1650 + 650,-1600 + 650,-1600
- + 650
-Sum: 71800
+ -1067150
+ +9000,-4450
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 550,- 550 + 600,- 550 + 600,- 500 + 600,-1650
+ + 650,-1600 + 650,-1650 + 600,-1600 + 650,- 500
+ + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650
+ + 650,- 500 + 600,-1650 + 600,- 500 + 650,- 500
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600
+Duration=71550us
+
Send Panasonic
-Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F202002 48 bits LSB first
+Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F202002 48 bits LSB first Gap=1065800us Duration=59800us
Send with: IrSender.sendPanasonic(0xF2, 0x87, );
rawData[100]:
- -1069050
- +3550,-1650
- + 500,- 400 + 500,-1250 + 500,- 350 + 500,- 400
- + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,- 350 + 500,-1250 + 500,- 400 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 350
- + 500,- 400 + 450,-1300 + 500,- 350 + 550,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400
- + 500,-1250 + 500,-1250 + 450,-1300 + 500,- 350
- + 500,- 400 + 450,- 400 + 500,- 400 + 450,-1300
- + 500,- 350 + 550,- 350 + 500,- 350 + 500,-1250
- + 550,- 350 + 500,-1250 + 450,- 400 + 550,-1200
- + 550
-Sum: 60000
+ -1065800
+ +3500,-1700
+ + 500,- 400 + 450,-1250 + 500,- 400 + 500,- 350
+ + 500,- 350 + 500,- 400 + 500,- 400 + 450,- 400
+ + 500,- 400 + 450,- 400 + 500,- 400 + 500,- 350
+ + 500,- 400 + 450,-1250 + 550,- 350 + 450,- 400
+ + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 450
+ + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 500,-1250
+ + 500,- 400 + 450,- 400 + 500,- 400 + 450,- 400
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,- 400
+ + 500,- 400 + 500,- 350 + 500,- 400 + 450,-1300
+ + 450,- 400 + 500,- 400 + 450,- 400 + 500,-1250
+ + 450,- 450 + 450,-1250 + 500,- 400 + 450,-1250
+ + 500
+Duration=59800us
+
Send Kaseikyo with 0x4711 as Vendor ID
-Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F234711 48 bits LSB first
+Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F234711 48 bits LSB first Gap=1091300us Duration=66700us
Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711);
rawData[100]:
- -1079750
- +3550,-1650
- + 550,-1200 + 550,- 350 + 500,- 350 + 550,- 350
- + 500,-1250 + 500,- 350 + 550,- 350 + 500,- 350
- + 550,-1200 + 550,-1200 + 550,-1200 + 550,- 350
- + 500,- 350 + 550,- 350 + 500,-1250 + 500,- 350
- + 550,-1200 + 550,-1200 + 550,- 350 + 500,- 350
- + 550,- 350 + 500,-1250 + 500,- 350 + 550,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1250
- + 500,- 300 + 550,- 400 + 500,- 350 + 550,- 350
- + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 350
- + 500,- 400 + 500,- 350 + 500,- 400 + 500,-1250
- + 500,-1250 + 500,-1250 + 500,- 350 + 500,-1250
- + 500,- 400 + 500,-1250 + 500,- 350 + 500,-1250
- + 550
-Sum: 67000
\ No newline at end of file
+ -1091300
+ +3500,-1650
+ + 500,-1250 + 500,- 400 + 500,- 350 + 500,- 400
+ + 450,-1300 + 450,- 400 + 450,- 450 + 450,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 500,- 400
+ + 450,- 400 + 500,- 400 + 450,-1250 + 500,- 400
+ + 500,-1250 + 450,-1300 + 450,- 400 + 500,- 400
+ + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 400
+ + 500,-1250 + 450,-1300 + 450,-1300 + 450,-1250
+ + 500,- 400 + 450,- 450 + 450,- 400 + 500,- 350
+ + 500,-1250 + 500,-1250 + 500,-1250 + 450,- 400
+ + 500,- 400 + 500,- 400 + 450,- 400 + 500,-1250
+ + 450,-1300 + 450,-1250 + 500,- 400 + 450,-1300
+ + 450,- 400 + 500,-1250 + 500,- 350 + 500,-1250
+ + 500
+Duration=66700us
+
+
+Send Kaseikyo_Denon variant
+Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F203254 48 bits LSB first Gap=1090350us Duration=63250us
+Send with: IrSender.sendKaseikyo_Denon(0xF2, 0x87, );
+rawData[100]:
+ -1090350
+ +3500,-1700
+ + 500,- 200 + 650,- 400 + 450,-1300 + 450,- 400
+ + 450,-1300 + 450,- 350 + 550,-1250 + 450,- 450
+ + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 400
+ + 450,-1300 + 450,-1250 + 500,- 400 + 500,- 400
+ + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 400
+ + 450,- 400 + 500,-1250 + 500,- 350 + 500,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 500,-1250
+ + 500,- 350 + 500,- 400 + 450,- 450 + 450,- 400
+ + 500,-1250 + 450,-1250 + 500,-1250 + 500,- 400
+ + 500,- 350 + 500,- 400 + 450,- 400 + 500,-1250
+ + 500,- 400 + 450,- 400 + 500,- 400 + 450,-1300
+ + 450,- 400 + 450,-1300 + 500,- 350 + 500,-1250
+ + 500
+Duration=63250us
+
+
+Send Denon
+Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first Gap=1088250us Duration=22350us
+Send with: IrSender.sendDenon(0x12, 0x87, );
+rawData[32]:
+ -1088250
+ + 300,- 750 + 300,-1800 + 300,- 750 + 300,- 750
+ + 300,-1800 + 300,-1800 + 300,-1800 + 300,-1800
+ + 300,- 700 + 350,- 700 + 300,- 750 + 300,- 750
+ + 300,-1850 + 300,- 750 + 300,- 700 + 350
+Duration=22350us
+
+
+Send Denon/Sharp variant
+Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x30F2 15 bits LSB first Gap=1035000us Duration=23350us
+Send with: IrSender.sendDenon(0x12, 0x87, );
+rawData[32]:
+ -1035000
+ + 300,- 750 + 300,-1750 + 300,- 750 + 300,- 750
+ + 300,-1800 + 300,-1800 + 300,-1800 + 300,-1800
+ + 300,- 750 + 300,- 750 + 300,- 750 + 300,- 750
+ + 300,-1750 + 350,-1750 + 350,- 750 + 300
+Duration=23350us
+
+
+Send Sony/SIRCS with 7 command and 5 address bits
+Protocol=Sony Address=0x12 Command=0x7 Raw-Data=0x907 12 bits LSB first Gap=1037100us Duration=20000us
+Send with: IrSender.sendSony(0x12, 0x7, 2, 12);
+rawData[26]:
+ -1037100
+ +2450,- 550
+ +1250,- 550 +1250,- 550 +1250,- 600 + 650,- 550
+ + 650,- 550 + 650,- 550 + 650,- 600 + 600,- 600
+ +1250,- 550 + 650,- 550 + 650,- 600 +1250
+Duration=20000us
+
+
+Send Sony/SIRCS with 7 command and 8 address bits
+Protocol=Sony Address=0xF2 Command=0x7 Raw-Data=0x7907 15 bits LSB first Gap=1047000us Duration=25400us
+Send with: IrSender.sendSony(0xF2, 0x7, 2, 15);
+rawData[32]:
+ -1047000
+ +2450,- 550
+ +1250,- 550 +1300,- 500 +1250,- 600 + 650,- 550
+ + 650,- 550 + 650,- 550 + 650,- 600 + 600,- 600
+ +1250,- 550 + 650,- 550 + 650,- 600 +1250,- 550
+ +1200,- 600 +1250,- 550 +1250
+Duration=25400us
+
+
+Send Sony/SIRCS with 7 command and 13 address bits
+Protocol=Sony Address=0xF2 Command=0x7 Raw-Data=0x7907 20 bits LSB first Gap=1057650us Duration=31500us
+Send with: IrSender.sendSony(0xF2, 0x7, 2, 20);
+rawData[42]:
+ -1057650
+ +2450,- 550
+ +1250,- 600 +1250,- 550 +1250,- 550 + 650,- 550
+ + 650,- 600 + 650,- 550 + 650,- 550 + 650,- 550
+ +1250,- 600 + 600,- 600 + 650,- 550 +1250,- 550
+ +1250,- 600 +1250,- 550 +1200,- 600 + 650,- 550
+ + 650,- 600 + 600,- 600 + 650,- 550 + 650
+Duration=31500us
+
+
+Send Samsung 8 bit command and 8 bit address
+Protocol=Samsung Address=0xF2 Command=0x87 Raw-Data=0x7887F2F2 32 bits LSB first Gap=1058000us Duration=65950us
+Send with: IrSender.sendSamsung(0xF2, 0x87, );
+rawData[68]:
+ -1058000
+ +4550,-4450
+ + 600,- 500 + 650,-1650 + 550,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500
+ + 650,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 650,- 500 + 600,- 550 + 600,- 550 + 600,-1600
+ + 650,- 500 + 600,- 550 + 600,- 500 + 650,-1650
+ + 550,-1650 + 650,-1650 + 550,-1650 + 650,- 500
+ + 600
+Duration=65950us
+
+
+Send Samsung 16 bit command and address
+Protocol=Samsung Address=0xF2 Command=0xA987 Raw-Data=0xA98700F2 32 bits LSB first Gap=1068650us Duration=60350us
+Send with: IrSender.sendSamsung(0xF2, 0xA987, );
+rawData[68]:
+ -1068650
+ +4500,-4450
+ + 600,- 500 + 650,-1600 + 600,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 550
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500
+ + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 550
+ + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650
+ + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600
+ + 600,- 550 + 600,-1650 + 600,- 500 + 650,-1650
+ + 600
+Duration=60350us
+
+
+Send Samsung48 16 bit command
+Protocol=Samsung48 Address=0xF2 Command=0xA987 Raw-Data=0x56A9788700F2 48 bits LSB first Gap=1067750us Duration=87450us
+Send with: IrSender.sendSamsung48(0xF2, 0xA987, );
+rawData[100]:
+ -1067750
+ +4550,-4400
+ + 650,- 500 + 650,-1600 + 600,- 550 + 600,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500
+ + 600,- 550 + 600,- 550 + 600,- 550 + 550,- 550
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550
+ + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1650
+ + 600,- 500 + 650,- 500 + 600,- 550 + 600,-1650
+ + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,-1650 + 600,- 550 + 600,- 550 + 600,-1650
+ + 600,- 550 + 550,-1650 + 650,- 500 + 600,-1650
+ + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 500
+ + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550
+ + 600
+Duration=87450us
+
+
+Send RC5
+Protocol=RC5 Address=0x12 Command=0x7 Raw-Data=0x1487 13 bits MSB first Gap=1089650us Duration=24200us
+Send with: IrSender.sendRC5(0x12, 0x7, );
+rawData[22]:
+ -1089650
+ + 950,- 850
+ +1800,-1750 +1800,- 850 + 950,-1750 +1850,- 850
+ + 900,- 850 + 950,- 850 + 950,-1750 + 950,- 850
+ + 900,- 900 + 950
+Duration=24200us
+
+
+Send RC5X with 7.th MSB of command set
+Protocol=RC5 Address=0x12 Command=0x47 Toggle=1 Raw-Data=0xC87 13 bits MSB first Gap=1046350us Duration=24250us
+Send with: IrSender.sendRC5(0x12, 0x47, );
+rawData[22]:
+ -1046350
+ +1850,-1750
+ + 950,- 850 +1800,- 850 + 950,-1750 +1850,- 850
+ + 900,- 900 + 900,- 850 + 950,-1750 + 950,- 850
+ + 900,- 900 + 950
+Duration=24250us
+
+
+Send RC6
+Protocol=RC6 Address=0xF2 Command=0x87 Toggle=1 Raw-Data=0x1F287 20 bits MSB first Gap=1042300us Duration=22950us
+Send with: IrSender.sendRC6(0xF2, 0x87, );
+rawData[36]:
+ -1042300
+ +2700,- 850
+ + 500,- 850 + 500,- 400 + 500,- 400 +1400,- 850
+ + 500,- 400 + 500,- 400 + 500,- 400 + 500,- 850
+ + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400
+ + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 400
+ + 500
+Duration=22950us
diff --git a/keywords.txt b/keywords.txt
index 935f913e1..03bdd2891 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -16,45 +16,56 @@ decodedIRData KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
-
-setFeedbackLED KEYWORD2
-enableLEDFeedback KEYWORD2
-enableLEDFeedbackForSend KEYWORD2
-disableLEDFeedback KEYWORD2
-disableLEDFeedbackForSend KEYWORD2
-printIRResultShort KEYWORD2
+# IRReceive
+available KEYWORD2
begin KEYWORD2
+decode KEYWORD2
+disableIRIn KEYWORD2
+enableIRIn KEYWORD2
+isIdle KEYWORD2
+printActiveIRProtocols KEYWORD2
+printIRResultMinimal KEYWORD2
+printIRResultRawFormatted KEYWORD2
+printIRResultShort KEYWORD2
+printIRSendUsage KEYWORD2
+registerReceiveCompleteCallback KEYWORD2
+restartAfterSend KEYWORD2
+restartTimer KEYWORD2
+restartTimerWithTicksToAdd KEYWORD2
+resume KEYWORD2
+setReceivePin KEYWORD2
start KEYWORD2
-available KEYWORD2
read KEYWORD2
stop KEYWORD2
end KEYWORD2
-enableLEDFeedback KEYWORD2
-decode KEYWORD2
-resume KEYWORD2
-enableIRIn KEYWORD2
-disableIRIn KEYWORD2
-sendNEC KEYWORD2
+
+# IRSend
setSendPin KEYWORD2
write KEYWORD2
-enableIROut KEYWORD2
-IRLedOff KEYWORD2
-sendRaw KEYWORD2
+sendApple KEYWORD2
+sendFAST KEYWORD2
sendJVC KEYWORD2
+sendLegoPowerFunctions KEYWORD2
sendLG KEYWORD2
-sendLGRepeat KEYWORD2
+sendLG2 KEYWORD2
+sendLG2Repeat KEYWORD2
sendLGRaw KEYWORD2
+sendMaranz KEYWORD2
+sendMagiQuest KEYWORD2
sendNEC KEYWORD2
+sendNEC2 KEYWORD2
sendNECRepeat KEYWORD2
sendNECRaw KEYWORD2
sendOnkyo KEYWORD2
-sendApple KEYWORD2
sendPanasonic KEYWORD2
+sendPronto KEYWORD2
sendKaseikyo KEYWORD2
sendKaseikyo_Denon KEYWORD2
sendKaseikyo_Sharp KEYWORD2
sendKaseikyo_JVC KEYWORD2
sendKaseikyo_Mitsubishi KEYWORD2
+sendRaw KEYWORD2
+sendRaw_P KEYWORD2
sendRC5 KEYWORD2
sendRC6 KEYWORD2
sendSamsungRepeat KEYWORD2
@@ -62,23 +73,42 @@ sendSamsung KEYWORD2
sendSharp KEYWORD2
sendSony KEYWORD2
sendSharpRaw KEYWORD2
-sendLegoPowerFunctions KEYWORD2
-sendMagiQuest KEYWORD2
-sendPronto KEYWORD2
-sendMagiQuest KEYWORD2
+sendVelux KEYWORD2
+
+# IRFeedbackLED
+disableLEDFeedback KEYWORD2
+disableLEDFeedbackForSend KEYWORD2
+enableLEDFeedback KEYWORD2
+enableLEDFeedbackForSend KEYWORD2
+setFeedbackLED KEYWORD2
+setLEDFeedback KEYWORD2
+
+# TinyIRReceiver
+disablePCIInterruptForTinyReceiver KEYWORD2
+enablePCIInterruptForTinyReceiver KEYWORD2
+initPCIInterruptForTinyReceiver KEYWORD2
+isIRReceiverAttachedForTinyReceiver KEYWORD2
+printTinyReceiverResultMinimal KEYWORD2
+TinyReceiverDecode KEYWORD2
+# TinyIRSender
+sendExtendedNEC KEYWORD2
sendFAST KEYWORD2
+
#######################################
# Constants (LITERAL1)
#######################################
+UNKNOWN LITERAL1
PULSE_DISTANCE LITERAL1
PULSE_WIDTH LITERAL1
+APPLE LITERAL1
DENON LITERAL1
-DISH LITERAL1
JVC LITERAL1
LG LITERAL1
LG2 LITERAL1
NEC LITERAL1
+NEC2 LITERAL1
+ONKYO LITERAL1
PANASONIC LITERAL1
KASEIKYO LITERAL1
KASEIKYO_JVC LITERAL1
@@ -87,18 +117,57 @@ KASEIKYO_SHARP LITERAL1
KASEIKYO_MITSUBISHI LITERAL1
RC5 LITERAL1
RC6 LITERAL1
+RC6A LITERAL1
SAMSUNG LITERAL1
+SAMSUNGLG LITERAL1
+SAMSUNG48 LITERAL1
SHARP LITERAL1
SONY LITERAL1
-ONKYO LITERAL1
-APPLE LITERAL1
BANG_OLUFSEN LITERAL1
BOSEWAVE LITERAL1
LEGO_PF LITERAL1
MAGIQUEST LITERAL1
WHYNTER LITERAL1
FAST LITERAL1
-UNKNOWN LITERAL1
-IR_RECEIVE_PIN LITERAL1
+
+IRDATA_FLAGS_IS_REPEAT LITERAL1
+IRDATA_FLAGS_IS_AUTO_REPEAT LITERAL1
+IRDATA_FLAGS_PARITY_FAILED LITERAL1
+IRDATA_FLAGS_TOGGLE_BIT LITERAL1
+IRDATA_FLAGS_EXTRA_INFO LITERAL1
+IRDATA_FLAGS_WAS_OVERFLOW LITERAL1
+IRDATA_FLAGS_IS_MSB_FIRST LITERAL1
+
+
+RAW_BUFFER_LENGTH LITERAL1
+EXCLUDE_UNIVERSAL_PROTOCOLS LITERAL1
+EXCLUDE_EXOTIC_PROTOCOLS LITERAL1
+IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK LITERAL1
+MARK_EXCESS_MICROS LITERAL1
+RECORD_GAP_MICROS LITERAL1
+DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE LITERAL1
+IR_INPUT_IS_ACTIVE_HIGH LITERAL1
IR_SEND_PIN LITERAL1
-FEEDBACK_LED_IS_ACTIVE_LOW LITERAL1
+SEND_PWM_BY_TIMER LITERAL1
+IR_SEND_DUTY_CYCLE_PERCENT LITERAL1
+USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN LITERAL1
+USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN LITERAL1
+USE_NO_SEND_PWM LITERAL1
+USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM LITERAL1
+DISABLE_CODE_FOR_RECEIVER LITERAL1
+FEEDBACK_LED_IS_ACTIVE_LOW LITERAL1
+NO_LED_FEEDBACK_CODE LITERAL1
+NO_LED_RECEIVE_FEEDBACK_CODE LITERAL1
+NO_LED_SEND_FEEDBACK_CODE LITERAL1
+MICROS_PER_TICK LITERAL1
+TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT LITERAL1
+
+# Constants for TinyIRReceiver
+IR_RECEIVE_PIN LITERAL1
+IR_FEEDBACK_LED_PIN LITERAL1
+DISABLE_PARITY_CHECKS LITERAL1
+USE_EXTENDED_NEC_PROTOCOL LITERAL1
+USE_ONKYO_PROTOCOL LITERAL1
+USE_FAST_PROTOCOL LITERAL1
+ENABLE_NEC2_REPEATS LITERAL1
+USE_CALLBACK_FOR_TINY_RECEIVER LITERAL1
diff --git a/library.json b/library.json
index eae4a2593..7aecaa48c 100644
--- a/library.json
+++ b/library.json
@@ -1,15 +1,14 @@
{
"name": "IRremote",
- "keywords": "communication, infrared, ir, remote",
+ "version": "4.5.0",
"description": "Send and receive infrared signals with multiple protocols",
+ "keywords": "communication, infrared, ir, remote",
+ "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote",
"repository":
{
"type": "git",
"url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git"
},
- "version": "4.4.0",
- "frameworks": "arduino",
- "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"],
"authors" :
[
{
@@ -26,5 +25,10 @@
"email":"ken.shirriff@gmail.com"
}
],
- "headers": "IRRemote.hpp"
+ "license": "MIT",
+ "frameworks": "arduino",
+ "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32", "raspberrypi"],
+ "headers": "IRRemote.hpp",
+ "examples": "examples/*/*.ino",
+ "export": {"exclude": [".github", "pictures"]}
}
diff --git a/library.properties b/library.properties
index e235679e6..ec368ba68 100644
--- a/library.properties
+++ b/library.properties
@@ -1,9 +1,9 @@
name=IRremote
-version=4.4.0
+version=4.5.0
author=shirriff, z3t0, ArminJo
maintainer=Armin Joachimsmeyer
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, Universal Pulse Distance and Pulse Width. NEW: TinyRSender improvements, sendSamsung bug fixes, new fields rawlen and initialGap and new functions stop/startTimer...().
+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, Velux, Universal Pulse Distance and Pulse Width.
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
diff --git a/pictures/IR_RobotCar.jpg b/pictures/IR_RobotCar.jpg
new file mode 100644
index 000000000..6258d0136
Binary files /dev/null and b/pictures/IR_RobotCar.jpg differ
diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp
index 97611b083..a40abdad6 100644
--- a/src/IRFeedbackLED.hpp
+++ b/src/IRFeedbackLED.hpp
@@ -40,102 +40,96 @@
* Contains pin number and enable status of the feedback LED
*/
struct FeedbackLEDControlStruct {
- uint8_t FeedbackLEDPin; ///< if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
- uint8_t LedFeedbackEnabled; ///< LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of pin on IR processing
+ uint8_t FeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN; ///< if USE_DEFAULT_FEEDBACK_LED_PIN / 0, then use digitalWriteFast(LED_BUILTIN,..) otherwise use digitalWrite(FeedbackLEDPin,..)
+ bool LedFeedbackEnabled; ///< Disabled for receive at default. Feedback for send is always enabled and can be disabled by NO_LED_SEND_FEEDBACK_CODE or #define NO_LED_FEEDBACK_CODE macros
};
struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED control instance
/**
- * Enable blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving
- * Cannot disable it here!!! Use disableLEDFeedbackForReceive() or disableLEDFeedbackForSend()
- * @param aFeedbackLEDPin If aFeedbackLEDPin == 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
- * If FeedbackLEDPin == 0 and no LED_BUILTIN defined, disable LED feedback
- * @param aEnableLEDFeedback If LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of Feedback LED
+ * @param aFeedbackLEDPin If FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN / 0, then use digitalWrite(FeedbackLEDPin,..)
+ * If FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN / 0 and no LED_BUILTIN defined, disable LED feedback
*/
-void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback) {
-
- FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; // default is 0 -> use LED_BUILTIN if available, else disable feedback
-
- if (aEnableLEDFeedback != DO_NOT_ENABLE_LED_FEEDBACK) {
- FeedbackLEDControl.LedFeedbackEnabled |= aEnableLEDFeedback;
- if (aFeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
- pinModeFast(aFeedbackLEDPin, OUTPUT);
-#if defined(LED_BUILTIN)
- } else {
- pinModeFast(LED_BUILTIN, OUTPUT);
-#else
- FeedbackLEDControl.LedFeedbackEnabled = LED_FEEDBACK_DISABLED_COMPLETELY; // we have no LED_BUILTIN available
-#endif
- }
- }
+void setLEDFeedbackPin(uint8_t aFeedbackLEDPin) {
+ FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin;
}
/*
* Direct replacement for blink13()
*/
void setLEDFeedback(bool aEnableLEDFeedback) {
- bool tEnableLEDFeedback = LED_FEEDBACK_DISABLED_COMPLETELY;
- if (aEnableLEDFeedback) {
- tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND | LED_FEEDBACK_ENABLED_FOR_RECEIVE;
- }
- setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, tEnableLEDFeedback);
+ FeedbackLEDControl.LedFeedbackEnabled = aEnableLEDFeedback;
}
+/*
+ * Historically this only affects receive LED
+ */
void enableLEDFeedback() {
- FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_RECEIVE;
+ FeedbackLEDControl.LedFeedbackEnabled = ENABLE_LED_FEEDBACK;
}
-
void disableLEDFeedback() {
- FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_RECEIVE);
-}
-
-void enableLEDFeedbackForSend() {
- FeedbackLEDControl.LedFeedbackEnabled |= LED_FEEDBACK_ENABLED_FOR_SEND;
-}
-
-void disableLEDFeedbackForSend() {
- FeedbackLEDControl.LedFeedbackEnabled &= ~(LED_FEEDBACK_ENABLED_FOR_SEND);
+ FeedbackLEDControl.LedFeedbackEnabled = DISABLE_LED_FEEDBACK;
}
/**
* Flash LED while receiving or sending IR data. Does not check if enabled, this must be done by the caller.
- * Handles the 0 value of FeedbackLEDPin and the macro FEEDBACK_LED_IS_ACTIVE_LOW.
+ * Handles the USE_DEFAULT_FEEDBACK_LED_PIN / 0 value of FeedbackLEDPin and the macro FEEDBACK_LED_IS_ACTIVE_LOW.
+ * If FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN and LED_BUILTIN is NOT defined no action is done
*/
#if defined(ESP32) || defined(ESP8266)
IRAM_ATTR
#endif
void setFeedbackLED(bool aSwitchLedOn) {
if (aSwitchLedOn) {
- if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
-#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
- digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED on
-#else
- digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED on
-#endif
+ // Turn user defined pin LED on
+ if (FeedbackLEDControl.FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN) {
#if defined(LED_BUILTIN) // use fast macros here
- } else {
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
- digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
+ digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
# else
- digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
+ digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
# endif
#endif
- }
- } else {
- if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) {
+
+ } else {
#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
- digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED off
+ if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) {
+ digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);
+ } else {
+ digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);
+ }
#else
- digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED off
+ if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin)) {
+ digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH);
+ } else {
+ digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);
+ }
#endif
+ }
+
+ } else {
+ // Turn user defined pin LED off
+ if (FeedbackLEDControl.FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN) {
#if defined(LED_BUILTIN)
- } else {
# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
- digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
+ digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command
# else
- digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
+ digitalWriteFast(LED_BUILTIN, LOW); // For AVR, this generates a single cbi command
# endif
+#endif
+ } else {
+#if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) {
+ digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH);
+ } else {
+ digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);
+ }
+#else
+ if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin)) {
+ digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);
+ } else {
+ digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);
+ }
#endif
}
}
@@ -145,13 +139,13 @@ void setFeedbackLED(bool aSwitchLedOn) {
* Old deprecated function name for setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()
*/
void IRrecv::blink13(uint8_t aEnableLEDFeedback) {
- setLEDFeedback(FeedbackLEDControl.FeedbackLEDPin, aEnableLEDFeedback);
+ setLEDFeedback(aEnableLEDFeedback);
}
/**
* Old deprecated function name for setLEDFeedback()
*/
void setBlinkPin(uint8_t aBlinkPin) {
- setLEDFeedback(aBlinkPin, FeedbackLEDControl.LedFeedbackEnabled);
+ setLEDFeedbackPin(aBlinkPin);
}
/** @}*/
diff --git a/src/IRProtocol.h b/src/IRProtocol.h
index 7a2bebddd..c9dd24cd4 100644
--- a/src/IRProtocol.h
+++ b/src/IRProtocol.h
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2024 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,6 +32,59 @@
#ifndef _IR_PROTOCOL_H
#define _IR_PROTOCOL_H
+/*
+ * If activated, BANG_OLUFSEN, BOSEWAVE, MAGIQUEST, WHYNTER, FAST and LEGO_PF are excluded in decoding and in sending with IrSender.write
+ */
+//#define EXCLUDE_EXOTIC_PROTOCOLS
+
+/*
+ * Supported IR protocols
+ * Each protocol you include costs memory and, during decode, costs time
+ * Copy the lines with the protocols you need in your program before the #include line
+ * See also SimpleReceiver example
+ */
+
+#if !defined(NO_DECODER) // for sending raw only
+# if (!(defined(DECODE_DENON) || defined(DECODE_JVC) || defined(DECODE_KASEIKYO) \
+|| defined(DECODE_PANASONIC) || defined(DECODE_LG) || defined(DECODE_NEC) || defined(DECODE_ONKYO) || defined(DECODE_SAMSUNG) \
+|| defined(DECODE_SONY) || defined(DECODE_RC5) || defined(DECODE_RC6) \
+|| defined(DECODE_DISTANCE_WIDTH) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
+|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_FAST) || defined(DECODE_WHYNTER)))
+/*
+ * If no protocol is explicitly enabled, we enable all protocols
+ */
+#define DECODE_DENON // Includes Sharp
+#define DECODE_JVC
+#define DECODE_KASEIKYO
+#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
+#define DECODE_LG
+#define DECODE_NEC // Includes Apple and Onkyo
+#define DECODE_SAMSUNG
+#define DECODE_SONY
+#define DECODE_RC5
+#define DECODE_RC6
+
+# if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory
+#define DECODE_BOSEWAVE
+#define DECODE_LEGO_PF
+#define DECODE_MAGIQUEST
+#define DECODE_WHYNTER
+#define DECODE_FAST
+# endif
+
+# if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS)
+#define DECODE_DISTANCE_WIDTH // universal decoder for pulse distance width protocols - requires up to 750 bytes additional program memory
+#define DECODE_HASH // special decoder for all protocols - requires up to 250 bytes additional program memory
+# endif
+# endif
+#endif // !defined(NO_DECODER)
+
+//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It prevents decoding of SONY!
+
+#if defined(DECODE_NEC) && !(~(~DECODE_NEC + 0) == 0 && ~(~DECODE_NEC + 1) == 1)
+#warning "The macros DECODE_XXX no longer require a value. Decoding is now switched by defining / non defining the macro."
+#endif
+
/**
* An enum consisting of all supported formats.
* You do NOT need to remove entries from this list when disabling protocols!
@@ -57,6 +110,7 @@ typedef enum {
KASEIKYO_MITSUBISHI,
RC5,
RC6,
+ RC6A, /*31 bit + 3 fixed 0b110 mode bits*/
SAMSUNG, /* 20*/
SAMSUNGLG,
SAMSUNG48,
@@ -68,7 +122,8 @@ typedef enum {
LEGO_PF,
MAGIQUEST,
WHYNTER, /* 30 */
- FAST
+ FAST,
+ OTHER
} decode_type_t;
extern const char *const ProtocolNames[]; // The array of name strings for the decode_type_t enum
@@ -99,53 +154,30 @@ struct DistanceWidthTimingInfoStruct {
#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
+#define IRDATA_FLAGS_LSB_MSB_FIRST_MASK IRDATA_FLAGS_IS_MSB_FIRST
-#define RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_RAW_DATA_TYPE)) + 1) // The -2 is for initial gap + stop bit mark, 128 mark + spaces for 64 bit.
-/**
- * Data structure for the user application, available as decodedIRData.
- * Filled by decoders and read by print functions or user application.
- */
-struct IRData {
- decode_type_t protocol; ///< UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
- uint16_t address; ///< Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << 8) | tSpaceTicksLong
- uint16_t command; ///< Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort
- uint16_t extra; ///< Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMarkTicks << 8) | HeaderSpaceTicks.
- IRRawDataType decodedRawData; ///< Up to 32/64 bit decoded raw data, to be used for send functions.
-#if defined(DECODE_DISTANCE_WIDTH)
- // This replaces the address, command, extra and decodedRawData in case of protocol == PULSE_DISTANCE or -rather seldom- protocol == PULSE_WIDTH.
- DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes
- IRRawDataType decodedRawDataArray[RAW_DATA_ARRAY_SIZE]; ///< 32/64 bit decoded raw data, to be used for send function.
-#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.
- * After resume(), decodedIRData.rawDataPtr->initialGapTicks and decodedIRData.rawDataPtr->rawlen are
- * the first variables, which are overwritten by the next received frame.
- * since 4.3.0.
- */
- IRRawlenType rawlen; ///< counter of entries in rawbuf of last received frame.
- uint16_t initialGapTicks; ///< contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
-
- irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR.
-};
+extern uint8_t sLastSendToggleValue; // Currently used by RC5 + RC6
struct PulseDistanceWidthProtocolConstants {
decode_type_t ProtocolIndex;
uint_fast8_t FrequencyKHz;
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo;
uint8_t Flags;
- unsigned int RepeatPeriodMillis;
+ unsigned int RepeatPeriodMillis; // Time between start of two frames. Thus independent from frame length.
void (*SpecialSendRepeatFunction)(); // using non member functions here saves up to 250 bytes for send demo
// void (IRsend::*SpecialSendRepeatFunction)();
};
/*
* Definitions for member PulseDistanceWidthProtocolConstants.Flags
*/
-#define SUPPRESS_STOP_BIT 0x20 // Stop bit is otherwise sent for all pulse distance protocols, i.e. aOneSpaceMicros != aZeroSpaceMicros.
-#define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST
-#define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST
+#define PROTOCOL_IS_PULSE_DISTANCE 0x00
+#define PROTOCOL_IS_PULSE_DISTANCE_WIDTH 0x00 // can often successfully be decoded as pulse distance
+#define PROTOCOL_IS_PULSE_WIDTH 0x10
+#define PROTOCOL_IS_PULSE_WIDTH_MASK PROTOCOL_IS_PULSE_WIDTH
+#define SUPPRESS_STOP_BIT 0x20 // Stop bit is otherwise sent for all pulse distance protocols, i.e. aOneSpaceMicros != aZeroSpaceMicros.
+#define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST
+#define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST
+#define PROTOCOL_IS_MSB_MASK IRDATA_FLAGS_IS_MSB_FIRST
/*
* Carrier frequencies for various protocols
@@ -168,7 +200,6 @@ const __FlashStringHelper* getProtocolString(decode_type_t aProtocol);
#else
const char* getProtocolString(decode_type_t aProtocol);
#endif
-void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintGap); // A static function to be able to print send or copied received data.
/*
* Convenience functions to convert MSB to LSB values
diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp
index e8c7a554c..aa058fa28 100644
--- a/src/IRProtocol.hpp
+++ b/src/IRProtocol.hpp
@@ -33,7 +33,7 @@
#ifndef _IR_PROTOCOL_HPP
#define _IR_PROTOCOL_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -62,6 +62,7 @@ const char string_Kaseikyo_JVC[] PROGMEM = "Kaseikyo_JVC";
const char string_Kaseikyo_Mitsubishi[] PROGMEM = "Kaseikyo_Mitsubishi";
const char string_RC5[] PROGMEM = "RC5";
const char string_RC6[] PROGMEM = "RC6";
+const char string_RC6A[] PROGMEM = "RC6A";
const char string_Samsung[] PROGMEM = "Samsung";
const char string_SamsungLG[] PROGMEM = "SamsungLG";
const char string_Samsung48[] PROGMEM = "Samsung48";
@@ -73,6 +74,7 @@ const char string_Lego[] PROGMEM = "Lego";
const char string_MagiQuest[] PROGMEM = "MagiQuest";
const char string_Whynter[] PROGMEM = "Whynter";
const char string_FAST[] PROGMEM = "FAST";
+const char string_Other[] PROGMEM = "OTHER";
/*
* !!Must be the same order as in decode_type_t in IRProtocol.h!!!
@@ -80,10 +82,10 @@ 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_SamsungLG, string_Samsung48,
- string_Sharp, string_Sony
+ string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_RC6A, 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
+ , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST, string_Other
#endif
};
@@ -149,112 +151,10 @@ namespace PrintULL {
# endif
#endif
-/**
- * Function to print decoded result and flags in one line.
- * A static function to be able to print data to send or copied received data.
- * Ends with println().
- *
- * @param aSerial The Print object on which to write, for Arduino you can use &Serial.
- * @param aIRDataPtr Pointer to the data to be printed.
- * @param aPrintRepeatGap If true also print the gap before repeats.
- *
+/** @}
+ * \addtogroup Utils Utility functions
+ * @{
*/
-void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) {
- if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) {
- aSerial->println(F("Overflow"));
- return;
- }
- aSerial->print(F("Protocol="));
- aSerial->print(getProtocolString(aIRDataPtr->protocol));
- if (aIRDataPtr->protocol == UNKNOWN) {
-#if defined(DECODE_HASH)
- aSerial->print(F(" Hash=0x"));
-#if (__INT_WIDTH__ < 32)
- aSerial->print(aIRDataPtr->decodedRawData, HEX);
-#else
- PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX);
-#endif
-
-#endif
-#if !defined(DISABLE_CODE_FOR_RECEIVER)
- aSerial->print(' ');
- aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC);
- aSerial->println(F(" bits (incl. gap and start) received"));
-#endif
- } else {
-#if defined(DECODE_DISTANCE_WIDTH)
- if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
-#endif
- /*
- * New decoders have address and command
- */
- aSerial->print(F(" Address=0x"));
- aSerial->print(aIRDataPtr->address, HEX);
-
- aSerial->print(F(" Command=0x"));
- aSerial->print(aIRDataPtr->command, HEX);
-
- if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
- aSerial->print(F(" Extra=0x"));
- aSerial->print(aIRDataPtr->extra, HEX);
- }
-
- if (aIRDataPtr->flags & IRDATA_FLAGS_PARITY_FAILED) {
- aSerial->print(F(" Parity fail"));
- }
-
- if (aIRDataPtr->flags & IRDATA_FLAGS_TOGGLE_BIT) {
- aSerial->print(F(" Toggle=1"));
- }
-#if defined(DECODE_DISTANCE_WIDTH)
- }
-#endif
- if (aIRDataPtr->flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
- aSerial->print(' ');
- if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
- aSerial->print(F("Auto-"));
- }
- aSerial->print(F("Repeat"));
-#if !defined(DISABLE_CODE_FOR_RECEIVER)
- if (aPrintRepeatGap) {
- aSerial->print(F(" gap="));
- aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK);
- aSerial->print(F("us"));
- }
-#else
- (void)aPrintRepeatGap;
-#endif
- }
-
- /*
- * Print raw data
- */
- if (!(aIRDataPtr->flags & IRDATA_FLAGS_IS_REPEAT) || aIRDataPtr->decodedRawData != 0) {
- aSerial->print(F(" Raw-Data=0x"));
-#if (__INT_WIDTH__ < 32)
- aSerial->print(aIRDataPtr->decodedRawData, HEX);
-#else
- PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX);
-#endif
- /*
- * Print number of bits processed
- */
- aSerial->print(' ');
- aSerial->print(aIRDataPtr->numberOfBits, DEC);
- aSerial->print(F(" bits"));
-
- if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
- aSerial->println(F(" MSB first"));
- } else {
- aSerial->println(F(" LSB first"));
- }
-
- } else {
- aSerial->println();
- }
- }
-}
-
/**********************************************************************************************************************
* Function to bit reverse OLD MSB values of e.g. NEC.
**********************************************************************************************************************/
diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp
index 61f5d407a..712545d53 100644
--- a/src/IRReceive.hpp
+++ b/src/IRReceive.hpp
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2009-2023 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
+ * Copyright (c) 2009-2025 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,8 +33,8 @@
#ifndef _IR_RECEIVE_HPP
#define _IR_RECEIVE_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
-//#define LOCAL_DEBUG //
+#if defined(DEBUG)
+#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
@@ -50,6 +50,10 @@
//#define _IR_MEASURE_TIMING // for ISR
//#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
//
+#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
+#define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
+#endif
+
/** \addtogroup Receiving Receiving IR data for multiple protocols
* @{
*/
@@ -61,26 +65,19 @@ IRrecv IrReceiver;
/*
* The control structure instance
*/
-struct irparams_struct irparams; // the irparams instance
+//struct irparams_struct irparams; // the irparams instance
+unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer()
/**
* Instantiate the IRrecv class. Multiple instantiation is not supported.
* @param IRReceivePin Arduino pin to use. No sanity check is made.
*/
IRrecv::IRrecv() {
- decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
setReceivePin(0);
-#if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
-#endif
}
IRrecv::IRrecv(uint_fast8_t aReceivePin) {
- decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
setReceivePin(aReceivePin);
-#if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
-#endif
}
/**
@@ -89,10 +86,9 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin) {
* @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
*/
IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
- decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
setReceivePin(aReceivePin);
-#if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(aFeedbackLEDPin, DO_NOT_ENABLE_LED_FEEDBACK);
+#if defined(LED_RECEIVE_FEEDBACK_CODE)
+ setLEDFeedbackPin(aFeedbackLEDPin);
#else
(void) aFeedbackLEDPin;
#endif
@@ -117,9 +113,12 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
*
**********************************************************************************************************************/
#if defined(ESP8266) || defined(ESP32)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvolatile"
IRAM_ATTR
#endif
-void IRReceiveTimerInterruptHandler() {
+
+void IRrecv::ReceiveInterruptHandler() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
@@ -136,11 +135,13 @@ void IRReceiveTimerInterruptHandler() {
uint_fast8_t tIRInputLevel = (uint_fast8_t) digitalReadFast(irparams.IRReceivePin);
#endif
+ uint_fast16_t tTickCounterForISR = irparams.TickCounterForISR;
/*
* Increase TickCounter and clip it at maximum 0xFFFF / 3.2 seconds at 50 us ticks
*/
if (irparams.TickCounterForISR < UINT16_MAX) {
- irparams.TickCounterForISR++; // One more 50uS tick
+ tTickCounterForISR++; // One more 50uS tick
+ irparams.TickCounterForISR = tTickCounterForISR;
}
/*
@@ -149,13 +150,14 @@ void IRReceiveTimerInterruptHandler() {
*/
// switch (irparams.StateForISR) {
//
- if (irparams.StateForISR == IR_REC_STATE_IDLE) {
+ uint_fast8_t tStateForISR = irparams.StateForISR;
+ if (tStateForISR == IR_REC_STATE_IDLE) {
/*
* Here we are just resumed and maybe in the middle of a transmission
*/
if (tIRInputLevel == INPUT_MARK) {
// check if we did not start in the middle of a transmission by checking the minimum length of leading space
- if (irparams.TickCounterForISR > RECORD_GAP_TICKS) {
+ if (tTickCounterForISR > RECORD_GAP_TICKS) {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
// digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
@@ -164,15 +166,18 @@ void IRReceiveTimerInterruptHandler() {
* Initialize all state machine variables
*/
irparams.OverflowFlag = false;
-// irparams.rawbuf[0] = irparams.TickCounterForISR;
- irparams.initialGapTicks = irparams.TickCounterForISR; // Enabling 8 bit buffer since 4.4
+ // irparams.rawbuf[0] = irparams.TickCounterForISR;
+ // Usage of initialGapTicks enables usage of 8 bit buffer instead of 16 bit since 4.4,
+ // because the big gap value is not stored in this buffer any more
+ irparams.initialGapTicks = tTickCounterForISR;
irparams.rawlen = 1;
irparams.StateForISR = IR_REC_STATE_MARK;
} // otherwise stay in idle state
irparams.TickCounterForISR = 0; // reset counter in both cases
}
- } else if (irparams.StateForISR == IR_REC_STATE_MARK) { // Timing mark
+ } else if (tStateForISR == IR_REC_STATE_MARK) {
+ // Timing mark here, rawlen is even
if (tIRInputLevel != INPUT_MARK) {
/*
* Mark ended here. Record mark time in rawbuf array
@@ -180,40 +185,28 @@ void IRReceiveTimerInterruptHandler() {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
// digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
#endif
- irparams.rawbuf[irparams.rawlen++] = irparams.TickCounterForISR; // record mark
+#if RECORD_GAP_TICKS <= 400
+ if (tTickCounterForISR > UINT8_MAX) {
+ tTickCounterForISR = UINT8_MAX;
+ }
+#endif
+ irparams.rawbuf[irparams.rawlen++] = tTickCounterForISR; // record mark
irparams.StateForISR = IR_REC_STATE_SPACE;
irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-)
}
- } else if (irparams.StateForISR == IR_REC_STATE_SPACE) { // Timing space
- if (tIRInputLevel == INPUT_MARK) {
- /*
- * Space ended here. Check for overflow and record space time in rawbuf array
- */
+ } else if (tStateForISR == IR_REC_STATE_SPACE) {
+ /*
+ * In space receiving here, rawlen is odd
+ * Check for timeout or overflow
+ */
+ if (tTickCounterForISR > RECORD_GAP_TICKS || irparams.rawlen >= RAW_BUFFER_LENGTH - 1) {
if (irparams.rawlen >= RAW_BUFFER_LENGTH) {
// Flag up a read OverflowFlag; Stop the state machine
irparams.OverflowFlag = true;
- irparams.StateForISR = IR_REC_STATE_STOP;
-#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
- /*
- * Call callback if registered (not NULL)
- */
- if (irparams.ReceiveCompleteCallbackFunction != NULL) {
- irparams.ReceiveCompleteCallbackFunction();
- }
-#endif
- } else {
-#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
-// digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
-#endif
- irparams.rawbuf[irparams.rawlen++] = irparams.TickCounterForISR; // record space
- irparams.StateForISR = IR_REC_STATE_MARK;
}
- irparams.TickCounterForISR = 0;
-
- } else if (irparams.TickCounterForISR > RECORD_GAP_TICKS) {
/*
- * Maximum space duration reached here.
+ * Overflow or maximum space duration reached here.
* Current code is ready for processing!
* We received a long space, which indicates gap between codes.
* Switch to IR_REC_STATE_STOP
@@ -221,23 +214,41 @@ void IRReceiveTimerInterruptHandler() {
*/
/*
* These 2 variables allow to call resume() directly after decode.
- * After resume(), decodedIRData.rawDataPtr->initialGapTicks and decodedIRData.rawDataPtr->rawlen are
+ * After resume(), irparams.initialGapTicks and irparams.rawlen are
* the first variables, which are overwritten by the next received frame.
* since 4.3.0.
+ * For backward compatibility, there are the same 2 statements in decode() if IrReceiver is not used.
*/
IrReceiver.decodedIRData.initialGapTicks = irparams.initialGapTicks;
IrReceiver.decodedIRData.rawlen = irparams.rawlen;
- irparams.StateForISR = IR_REC_STATE_STOP;
+
+ irparams.StateForISR = IR_REC_STATE_STOP; // This signals the decode(), that a complete frame was received
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
/*
- * Call callback if registered (not NULL)
+ * Call callback if registered (not nullptr)
*/
- if (irparams.ReceiveCompleteCallbackFunction != NULL) {
+ if (irparams.ReceiveCompleteCallbackFunction != nullptr) {
irparams.ReceiveCompleteCallbackFunction();
}
#endif
+ } else if (tIRInputLevel == INPUT_MARK) {
+ /*
+ * Space ended here.
+ */
+
+#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
+// digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
+#endif
+#if RECORD_GAP_TICKS <= 400
+ if (tTickCounterForISR > UINT8_MAX) {
+ tTickCounterForISR = UINT8_MAX;
+ }
+#endif
+ irparams.rawbuf[irparams.rawlen++] = tTickCounterForISR; // record space
+ irparams.StateForISR = IR_REC_STATE_MARK;
+ irparams.TickCounterForISR = 0;
}
- } else if (irparams.StateForISR == IR_REC_STATE_STOP) {
+ } else if (tStateForISR == IR_REC_STATE_STOP) {
/*
* Complete command received
* stay here until resume() is called, which switches state to IR_REC_STATE_IDLE
@@ -251,8 +262,8 @@ void IRReceiveTimerInterruptHandler() {
}
}
-#if !defined(NO_LED_FEEDBACK_CODE)
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_RECEIVE) {
+#if defined(LED_RECEIVE_FEEDBACK_CODE)
+ if (FeedbackLEDControl.LedFeedbackEnabled) {
setFeedbackLED(tIRInputLevel == INPUT_MARK);
}
#endif
@@ -262,9 +273,22 @@ void IRReceiveTimerInterruptHandler() {
#endif
}
-
/*
- * The ISR, which calls the interrupt handler
+ * The handler which directly calls the interrupt handler function of the IRrecv object.
+ * This must be a separate function, because we need this static function in IRTimer.hpp.
+ * Doing it this way, we are able to modify the body of this function to support multiple IRrecv instances for receiving
+ */
+void IRReceiveTimerInterruptHandler() {
+ IrReceiver.ReceiveInterruptHandler();
+#if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES)
+ // Quick and dirty solution by used defined extension
+ UserIRReceiveTimerInterruptHandler();
+#endif
+}
+
+/**********************************************************************************************************************
+ * Interrupt Service Routine - Called every 50 us
+ * This in turn calls calls the static interrupt handler function, which in turn calls the interrupt handler function of the IRrecv object
*/
#if defined(TIMER_INTR_NAME) || defined(ISR)
# if defined(TIMER_INTR_NAME)
@@ -281,6 +305,7 @@ ISR()
/**********************************************************************************************************************
* Stream like API
**********************************************************************************************************************/
+
/**
* Initializes the receive and feedback pin
* @param aReceivePin The Arduino pin number, where a demodulating IR receiver is connected.
@@ -290,12 +315,9 @@ ISR()
void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
setReceivePin(aReceivePin);
-#if !defined(NO_LED_FEEDBACK_CODE)
- uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
- if (aEnableLEDFeedback) {
- tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE;
- }
- setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
+#if defined(LED_RECEIVE_FEEDBACK_CODE)
+ setLEDFeedback(aEnableLEDFeedback);
+ setLEDFeedbackPin(aFeedbackLEDPin);
#else
(void) aEnableLEDFeedback;
(void) aFeedbackLEDPin;
@@ -335,13 +357,18 @@ void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) {
irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
# endif
#endif
+ // 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 (__builtin_constant_p(aReceivePinNumber)) {
+ pinModeFast(aReceivePinNumber, INPUT);
+ } else {
+ pinModeFast(aReceivePinNumber, INPUT);
+ }
}
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
/**
- * Sets the function to call if a protocol message has arrived
+ * Sets the function to call if a complete protocol frame has arrived
*/
void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) {
irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction;
@@ -369,12 +396,16 @@ void IRrecv::start() {
}
/*
- * Do not resume() reading of IR data
+ * Restarts timer interrupts, adjusts TickCounterForISR for correct gap value after stopTimer(). Does not call resume()!
*/
void IRrecv::restartTimer() {
// Setup for cyclic 50 us interrupt
timerConfigForReceive(); // no interrupts enabled here!
// Timer interrupt is enabled after state machine reset
+ if (sMicrosAtLastStopTimer != 0) {
+ irparams.TickCounterForISR += (micros() - sMicrosAtLastStopTimer) / MICROS_PER_TICK; // adjust TickCounterForISR for correct gap value, which is used for repeat detection
+ sMicrosAtLastStopTimer = 0;
+ }
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);
@@ -388,34 +419,39 @@ void IRrecv::enableIRIn() {
}
/**
- * Configures the timer and the state machine for IR reception.
+ * Configures the timer and the state machine for IR reception. Does not call resume()!
+ * We assume, that timer interrupts are disabled here, otherwise it makes no sense to use this functions.
+ * Therefore we do not need to guard the change of the volatile TickCounterForISR here :-).
* The tick counter value is already at 100 when decode() gets true, because of the 5000 us minimal gap defined in RECORD_GAP_MICROS.
+ * If TickCounterForISR is not adjusted with the value of the microseconds, the timer was stopped,
+ * it can happen, that a new IR frame is recognized as a repeat, because the value of RECORD_GAP_MICROS
+ * was not reached by TickCounterForISR counter before receiving the new IR frame.
* @param aMicrosecondsToAddToGapCounter To compensate for the amount of microseconds the timer was stopped / disabled.
*/
-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();
+ timerConfigForReceive(); // no interrupts enabled here!
+ 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
}
+/**
+ * Configures the timer and the state machine for IR reception. Does not call resume()!
+ * @param aTicksToAddToGapCounter To compensate for the amount of ticks the timer was stopped / disabled.
+ */
void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
irparams.TickCounterForISR += aTicksToAddToGapCounter;
- restartTimer();
-}
-
-void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) {
- irparams.TickCounterForISR += aTicksToAddToInternalTickCounter;
+ timerConfigForReceive(); // no interrupts enabled here!
+ 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
}
+#if defined(ESP8266) || defined(ESP32)
+#pragma GCC diagnostic push
+#endif
-void IRrecv::addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter) {
- irparams.TickCounterForISR += aMicrosecondsToAddToInternalTickCounter / MICROS_PER_TICK;
-}
/**
* Restarts receiver after send. Is a NOP if sending does not require a timer.
*/
@@ -432,8 +468,12 @@ void IRrecv::stop() {
timerDisableReceiveInterrupt();
}
+/*
+ * Stores microseconds of stop, to adjust TickCounterForISR in restartTimer()
+ */
void IRrecv::stopTimer() {
timerDisableReceiveInterrupt();
+ sMicrosAtLastStopTimer = micros();
}
/**
* Alias for stop().
@@ -504,16 +544,16 @@ bool IRrecv::available() {
}
/**
- * If IR receiver data is available, returns pointer to IrReceiver.decodedIRData, else NULL.
+ * Returns pointer to IrReceiver.decodedIRData if IR receiver data is available, else nullptr.
*/
IRData* IRrecv::read() {
if (irparams.StateForISR != IR_REC_STATE_STOP) {
- return NULL;
+ return nullptr;
}
if (decode()) {
return &decodedIRData;
} else {
- return NULL;
+ return nullptr;
}
}
@@ -528,6 +568,14 @@ bool IRrecv::decode() {
return false;
}
+ /*
+ * Support for old examples, which do not use the default IrReceiver instance
+ */
+ if (this != &IrReceiver) {
+ decodedIRData.initialGapTicks = irparams.initialGapTicks;
+ decodedIRData.rawlen = irparams.rawlen;
+ }
+
initDecodedIRData(); // sets IRDATA_FLAGS_WAS_OVERFLOW
if (decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) {
@@ -633,7 +681,7 @@ bool IRrecv::decode() {
#endif
#if defined(DECODE_BOSEWAVE)
- IR_TRACE_PRINTLN(F("Attempting Bosewave decode"));
+ IR_TRACE_PRINTLN(F("Attempting Bosewave decode"));
if (decodeBoseWave()) {
return true;
}
@@ -679,58 +727,128 @@ bool IRrecv::decode() {
* Common decode functions
**********************************************************************************************************************/
/**
- * Decode pulse distance width protocols. We only check the mark or space length of a 1, otherwise we always assume a 0!
+ * Decode pulse distance width protocols. We only check the mark or space length of a 1 against a threshold value, otherwise we always assume a 0!
+ * using matchMark() and matchSpace(), which includes MARK_EXCESS_MICROS in comparison.
*
* We can have the following protocol timings
* PULSE_DISTANCE: Pause/spaces have different length and determine the bit value, longer space is 1. Pulses/marks can be constant, like NEC.
* PULSE_WIDTH: Pulses/marks have different length and determine the bit value, longer mark is 1. Pause/spaces can be constant, like Sony.
- * PULSE_DISTANCE_WIDTH: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. Can be decoded by PULSE_DISTANCE decoder.
+ * PULSE_DISTANCE_WIDTH: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. Can be decoded using the PULSE_DISTANCE decoding.
*
- * Input is IrReceiver.decodedIRData.rawDataPtr->rawbuf[]
+ * Input is IrReceiver.irparams.rawbuf[]
* Output is IrReceiver.decodedIRData.decodedRawData
*
- * Assume PULSE_DISTANCE if aOneMarkMicros == aZeroMarkMicros
- *
- * @param aNumberOfBits Number of bits to decode from decodedIRData.rawDataPtr->rawbuf[] array.
- * @param aStartOffset Offset in decodedIRData.rawDataPtr->rawbuf[] to start decoding. Must point to a mark.
- * @param aOneMarkMicros Checked if PULSE_WIDTH
- * @param aZeroMarkMicros Required for deciding if we have PULSE_DISTANCE.
- * @param aOneSpaceMicros Checked if PULSE_DISTANCE.
- * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first.
- * @return true If decoding was successful
+ * @param aNumberOfBits Number of bits to decode from irparams.rawbuf[] array.
+ * @param aStartOffset Offset in irparams.rawbuf[] to start decoding. Must point to a mark.
+ * @param aOneMicros Timing value for 1
+ * @param aIsPulseWidthProtocol If true the aOneThresholdMicros id the mark threshold for 1, otherwise the space threshold
+ * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first.
*/
-bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
- uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) {
+void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMicros,
+ bool aIsPulseWidthProtocol, bool aMSBfirst) {
- auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
-
- bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we check aOneSpaceMicros -> pulse distance protocol
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("aOneMicros="));
+ Serial.print(aOneMicros);
+ Serial.print(F(", 0.75*aOneMicros="));
+ Serial.print((aOneMicros * 3) / 4);
+ Serial.print(F(", MARK_EXCESS_MICROS=" STR(MARK_EXCESS_MICROS) " isPulseWidthProtocol="));
+ Serial.print(aIsPulseWidthProtocol);
+ Serial.println();
+#endif
IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
IRRawDataType tMask = 1UL; // Mask is only used for LSB first
+ auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
- // get one mark and space pair
- unsigned int tMarkTicks;
- unsigned int tSpaceTicks;
- bool tBitValue;
- if (isPulseDistanceProtocol) {
+ bool tBitValue;
+ uint16_t tCurrentTicks;
+ if (aIsPulseWidthProtocol) {
+ /*
+ * PULSE_WIDTH here.
+ * !!!We only check variable length mark indicating a 1 or 0!!!
+ */
+ tCurrentTicks = *tRawBufPointer++;
+ tBitValue = matchMark(tCurrentTicks, aOneMicros); // Check for variable length mark indicating a 1 or 0
+ tRawBufPointer++;
+ } else {
/*
* PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
* !!!We only check variable length space indicating a 1 or 0!!!
*/
tRawBufPointer++;
- tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
- tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
+ tCurrentTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
+ tBitValue = matchSpace(tCurrentTicks, aOneMicros); // Check for variable length space indicating a 1 or 0
+ }
+
+ if (aMSBfirst) {
+ tDecodedData <<= 1;
+ }
+ if (tBitValue) {
+ // It's a 1 -> set the bit
+ if (aMSBfirst) {
+ tDecodedData |= 1;
+ } else {
+ tDecodedData |= tMask;
+ }
+ IR_TRACE_PRINT(tCurrentTicks);
+ IR_TRACE_PRINTLN(F(" => 1"));
} else {
- /*
- * PULSE_WIDTH here.
- * !!!We only check variable length mark indicating a 1 or 0!!!
- */
- tMarkTicks = *tRawBufPointer++;
- tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
+ // do not set the bit
+ IR_TRACE_PRINT(tCurrentTicks);
+ IR_TRACE_PRINTLN(F(" => 0"));
+ }
+ tMask <<= 1;
+ }
+ decodedIRData.decodedRawData = tDecodedData;
+}
+
+/**
+ * New threshold decoder to be activated by USE_THRESHOLD_DECODER
+ * Assumes a 0 for shorter and a 1 for longer timing. Thus the value must be eventually inverted by the calling protocol decoder (MagiQuest).
+ * In normal decoder we check the if we have a timing for a 1 (normally the longer timing) within a range of 75 % and 125 % of the nominal timing see TICKS_LOW.
+ * Many protocols have a ratio of 1 to 3 between short and long timing. In this case this decoder extends the range to 66% and the upper bound does not matter anyway.
+ * I hope that this will give slightly better results especially for
+ * - jittering signals
+ * - protocols with a smaller timing ratio than 1 to 2
+ * - protocols with short 1 pulses / pauses like MagiQuest.
+ * Requires up to 458 bytes more program space, if more than 1 protocol is involved.
+ * but saves 90 bytes if only e.g. NEC is selected.
+ *
+ * @param aNumberOfBits Number of bits to decode from irparams.rawbuf[] array.
+ * @param aStartOffset Offset in irparams.rawbuf[] to start decoding. Must point to a mark.
+ * @param aOneThresholdMicros Threshold value for 1
+ * @param aIsPulseWidthProtocol If true the aOneThresholdMicros id the mark threshold for 1, otherwise the space threshold
+ * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first.
+ */
+void IRrecv::decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset,
+ uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst) {
+
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("OneThresholdMicros="));
+ Serial.print(aOneThresholdMicros);
+ Serial.print(F(" isPulseWidthProtocol="));
+ Serial.print(aIsPulseWidthProtocol);
+ Serial.println();
+#endif
+
+ IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
+ IRRawDataType tMask = 1UL; // Mask is only used for LSB first
+ auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
+
+ for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
+
+ if (!aIsPulseWidthProtocol) {
+ tRawBufPointer++;
+ }
+ uint16_t tCurrentMicros = *tRawBufPointer * MICROS_PER_TICK;
+ bool tBitValue = tCurrentMicros > aOneThresholdMicros; // Check for variable length timing indicating a 1 or 0
+ tRawBufPointer++;
+
+ if (aIsPulseWidthProtocol) {
tRawBufPointer++;
}
@@ -745,26 +863,27 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy
} else {
tDecodedData |= tMask;
}
- IR_TRACE_PRINTLN(F("=> 1"));
+ IR_TRACE_PRINT(tCurrentMicros);
+ IR_TRACE_PRINTLN(F(" => 1"));
} else {
// do not set the bit
- IR_TRACE_PRINTLN(F("=> 0"));
+ IR_TRACE_PRINT(tCurrentMicros);
+ IR_TRACE_PRINTLN(F(" => 0"));
}
tMask <<= 1;
}
decodedIRData.decodedRawData = tDecodedData;
- return true;
}
-/*
- * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter
+/**
+ * Old deprecated version with 3 timing parameters instead of one and a aIsPulseWidthProtocol flag
*/
-bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
- uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
+void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) {
- (void) aZeroSpaceMicros;
- auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
- bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
+ auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
+
+ bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we check aOneSpaceMicros -> pulse distance protocol
IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
IRRawDataType tMask = 1UL; // Mask is only used for LSB first
@@ -777,16 +896,17 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy
if (isPulseDistanceProtocol) {
/*
- * Pulse distance here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration.
+ * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
+ * !!!We only check variable length space indicating a 1 or 0!!!
*/
-
- (void) aZeroSpaceMicros;
tRawBufPointer++;
tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
+
} else {
/*
- * Pulse width here, it is not required to check (constant) space duration and zero mark duration.
+ * PULSE_WIDTH here.
+ * !!!We only check variable length mark indicating a 1 or 0!!!
*/
tMarkTicks = *tRawBufPointer++;
tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
@@ -812,22 +932,32 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy
tMask <<= 1;
}
decodedIRData.decodedRawData = tDecodedData;
- return true;
}
/*
+ * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter
+ */
+void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
+
+ (void) aZeroSpaceMicros;
+ decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aOneMarkMicros, aZeroMarkMicros, aOneSpaceMicros, aMSBfirst);
+}
+
+/*
+ * Only sensible for development or very exotic requirements. - Not used yet
* 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.
- * Only sensible for development or very exotic requirements.
+ *
* @param aZeroMarkMicros For strict checks
* @param aZeroSpaceMicros For strict checks
+ * @return true if decoding successful
*
- * Not used yet
*/
-bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
- uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
+bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
- auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
+ auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
@@ -842,13 +972,14 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa
if (isPulseDistanceProtocol) {
/*
- * PULSE_DISTANCE here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration.
+ * PULSE_DISTANCE here (aOneMarkMicros == aZeroMarkMicros)
+ * We additionally check constant mark duration and in case of zero the zero space duration.
*/
tMarkTicks = *tRawBufPointer++;
tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
- // Check for constant length mark
+ // Check for constant mark duration
if (!matchMark(tMarkTicks, aOneMarkMicros)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Mark="));
@@ -862,15 +993,57 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa
return false;
}
+ // in case of 0, check for zero space duration
+ if (!tBitValue && !matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("Space="));
+ Serial.print(tSpaceTicks * MICROS_PER_TICK);
+ Serial.print(F(" is not "));
+ Serial.print(aZeroSpaceMicros);
+ Serial.print(F(". Index="));
+ Serial.print(aNumberOfBits - i);
+ Serial.print(' ');
+#endif
+ return false;
+ }
+
} else {
/*
- * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
- * !!!We only check variable length mark indicating a 1 or 0!!!
- * It is not required to check space duration and zero mark duration.
+ * PULSE_WIDTH -including PULSE_DISTANCE_WIDTH- here.
+ * We additionally check two space durations and in case of zero the zero mark duration.
*/
tMarkTicks = *tRawBufPointer++;
tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
+
+ // Check for space length, which is not constant in case of PULSE_DISTANCE_WIDTH
+ if ((tBitValue && !matchSpace(tSpaceTicks, aOneSpaceMicros))
+ || ((!tBitValue && !matchSpace(tSpaceTicks, aZeroSpaceMicros)))) {
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("Space="));
+ Serial.print(tSpaceTicks * MICROS_PER_TICK);
+ Serial.print(F(" is not "));
+ Serial.print(aOneSpaceMicros);
+ Serial.print(F(" or "));
+ Serial.print(aZeroSpaceMicros);
+ Serial.print(F(". Index="));
+ Serial.print(aNumberOfBits - i);
+ Serial.print(' ');
+#endif
+ return false;
+ }
+ if (!tBitValue && !matchMark(tMarkTicks, aZeroMarkMicros)) {
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("Mark="));
+ Serial.print(tMarkTicks * MICROS_PER_TICK);
+ Serial.print(F(" is not "));
+ Serial.print(aZeroMarkMicros);
+ Serial.print(F(". Index="));
+ Serial.print(aNumberOfBits - i);
+ Serial.print(' ');
+#endif
+ return false;
+ }
}
if (aMSBfirst) {
@@ -886,61 +1059,9 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa
}
IR_TRACE_PRINTLN(F("=> 1"));
} else {
- /*
- * Additionally check length of tSpaceTicks parameter for PULSE_DISTANCE or tMarkTicks for PULSE_WIDTH
- * which determine a zero
- */
- if (isPulseDistanceProtocol) {
- if (!matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Space="));
- Serial.print(tSpaceTicks * MICROS_PER_TICK);
- Serial.print(F(" is not "));
- Serial.print(aOneSpaceMicros);
- Serial.print(F(" or "));
- Serial.print(aZeroSpaceMicros);
- Serial.print(F(". Index="));
- Serial.print(aNumberOfBits - i);
- Serial.print(' ');
-#endif
- return false;
- }
- } else {
- if (!matchMark(tMarkTicks, aZeroMarkMicros)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Mark="));
- Serial.print(tMarkTicks * MICROS_PER_TICK);
- Serial.print(F(" is not "));
- Serial.print(aOneMarkMicros);
- Serial.print(F(" or "));
- Serial.print(aZeroMarkMicros);
- Serial.print(F(". Index="));
- Serial.print(aNumberOfBits - i);
- Serial.print(' ');
-#endif
- return false;
- }
- }
// do not set the bit
IR_TRACE_PRINTLN(F("=> 0"));
}
- // If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
- if (aZeroSpaceMicros == aOneSpaceMicros
- && tRawBufPointer < &decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen]) {
- // Check for constant length space (of pulse width protocol) here
- if (!matchSpace(tSpaceTicks, aOneSpaceMicros)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Space="));
- Serial.print(tSpaceTicks * MICROS_PER_TICK);
- Serial.print(F(" is not "));
- Serial.print(aOneSpaceMicros);
- Serial.print(F(". Index="));
- Serial.print(aNumberOfBits - i);
- Serial.print(' ');
-#endif
- return false;
- }
- }
tMask <<= 1;
}
decodedIRData.decodedRawData = tDecodedData;
@@ -951,12 +1072,55 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa
* Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
* @return true if decoding was successful
*/
-bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
+#if defined(USE_STRICT_DECODER)
+bool
+#else
+void
+#endif
+IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
IRRawlenType aStartOffset) {
- return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
- aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
- aProtocolConstants->Flags);
+#if defined(USE_STRICT_DECODER)
+ return decodeStrictPulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
+
+#else
+ bool tIsPulseWidthProtocol = aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK;
+ uint16_t tThresholdMicros;
+
+# if defined(USE_THRESHOLD_DECODER)
+ if (tIsPulseWidthProtocol) {
+ // we check the length of marks here
+ tThresholdMicros = ((aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros
+ + aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros) / 2) - MARK_EXCESS_MICROS;// MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
+ } else {
+ // we check the length of spaces here
+ tThresholdMicros = ((aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros
+ + aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros) / 2) + MARK_EXCESS_MICROS;// MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
+ }
+ return decodeWithThresholdPulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros,
+ aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
+# else
+ if (tIsPulseWidthProtocol) {
+ tThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros;
+ } else {
+ tThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros;
+ }
+ decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros,
+ aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
+# endif
+#endif
+}
+
+void IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) {
+
+ PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
+ memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
+ sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
+
+ decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset);
}
/*
@@ -1002,7 +1166,7 @@ uint_fast8_t IRrecv::getBiphaselevel() {
* Setup data if sUsedTimingIntervals is 0
*/
if (sBiphaseUsedTimingIntervals == 0) {
- uint16_t tCurrentTimingWith = decodedIRData.rawDataPtr->rawbuf[sBiphaseDecodeRawbuffOffset];
+ uint16_t tCurrentTimingWith = irparams.rawbuf[sBiphaseDecodeRawbuffOffset];
uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS;
if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) {
@@ -1053,16 +1217,16 @@ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
}
/**
- * decodeHash - decode an arbitrary IR code.
+ * Decodes an arbitrary IR code to a 32-bit value.
* 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 and SPACE signals, and see if each one
+ * The algorithm looks 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.
+ * It 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
+ * Uses FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
* Converts the raw code values into a 32-bit hash code.
* Hopefully this code is unique for each button.
* This isn't a "real" decoding, just an arbitrary value.
@@ -1082,7 +1246,7 @@ bool IRrecv::decodeHash() {
}
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]);
+ uint_fast8_t value = compare(irparams.rawbuf[i], irparams.rawbuf[i + 2]);
// Add value into the hash
hash = (hash * FNV_PRIME_32) ^ value;
}
@@ -1125,17 +1289,36 @@ bool IRrecv::decodeHashOld(decode_results *aResults) {
*/
bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants) {
// Check header "mark" and "space"
- if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros)) {
+ if (!matchMark(irparams.rawbuf[1], aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros)) {
+#if defined(LOCAL_TRACE)
+ Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
+ Serial.println(F(": Header mark length is wrong"));
+#endif
+ return false;
+ }
+ if (!matchSpace(irparams.rawbuf[2], aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros)) {
+#if defined(LOCAL_TRACE)
+ Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
+ Serial.println(F(": Header space length is wrong"));
+#endif
+ return false;
+ }
+ return true;
+}
+
+bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM) {
+// Check header "mark" and "space"
+ if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) {
#if defined(LOCAL_TRACE)
- Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
- Serial.println(F(": Header mark length is wrong"));
+ Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex)));
+ Serial.println(F(": Header mark length is wrong"));
#endif
return false;
}
- if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros)) {
+ if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) {
#if defined(LOCAL_TRACE)
- Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
- Serial.println(F(": Header space length is wrong"));
+ Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex)));
+ Serial.println(F(": Header space length is wrong"));
#endif
return false;
}
@@ -1143,14 +1326,15 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants
}
/*
- * Do not check for same address and command, because it is almost not possible to press 2 different buttons on the remote within around 100 ms.
+ * Does not check for same address and command, because it is almost not possible to press 2 different buttons on the remote within around 100 ms.
* And if really required, it can be enabled here, or done manually in user program.
* And we have still no RC6 toggle bit check for detecting a second press on the same button.
*/
void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks) {
if (decodedIRData.initialGapTicks < aMaximumRepeatSpaceTicks
-#if defined(ENABLE_FULL_REPEAT_CHECK)
- && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 85 bytes program space */
+#if defined(ENABLE_COMPLETE_REPEAT_CHECK)
+// Check also for same command and address values to detect a repeat. Not sensible for standard protocols, because it is almost not possible to press 2 different buttons on the remote within around 100 ms
+ && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 44 bytes program space */
#endif
) {
decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
@@ -1158,32 +1342,66 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTick
}
/**
- * Match function without compensating for marks exceeded or spaces shortened by demodulator hardware
+ * Match function WITHOUT compensating for marks exceeded or spaces shortened by demodulator hardware
* @return true, if values match
- * Currently not used
*/
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
+ uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK);
+ uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4;
#if defined(LOCAL_TRACE)
- Serial.print(F("Testing: "));
- Serial.print(TICKS_LOW(aMatchValueMicros), DEC);
- Serial.print(F(" <= "));
- Serial.print(aMeasuredTicks, DEC);
- Serial.print(F(" <= "));
- Serial.print(TICKS_HIGH(aMatchValueMicros), DEC);
-#endif
- bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
+ Serial.print(F("Testing (actual vs desired): "));
+ Serial.print(tMeasuredMicros);
+ Serial.print(F("us vs "));
+ Serial.print(aMatchValueMicros);
+ Serial.print(F("us: "));
+ Serial.print(tMatchValueMicrosQuarter * 3); // rounded value because we divide first
+ Serial.print(F(" <= "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(tMatchValueMicrosQuarter * 5);
+#endif
+ bool passed = (tMeasuredMicros >= (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5));
#if defined(LOCAL_TRACE)
- if (passed) {
- Serial.println(F(" => passed"));
- } else {
- Serial.println(F(" => FAILED"));
- }
+ if (passed) {
+ Serial.println(F(" => passed"));
+ } else {
+ Serial.println(F(" => FAILED"));
+ }
#endif
return passed;
}
-bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
- return matchTicks(measured_ticks, desired_us);
+/**
+ * Match function WITH compensating for marks exceeded or spaces shortened by demodulator hardware
+ * @return true, if values match
+ */
+bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks) {
+ uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK) + aCompensationMicrosForTicks;
+ uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4;
+#if defined(LOCAL_TRACE)
+ Serial.print(F("Testing (actual vs desired): "));
+ Serial.print(tMeasuredMicros);
+ Serial.print(F("us vs "));
+ Serial.print(aMatchValueMicros);
+ Serial.print(F("us: "));
+ Serial.print(tMatchValueMicrosQuarter * 3); // rounded value because we divide first
+ Serial.print(F(" < "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(tMatchValueMicrosQuarter * 5);
+#endif
+ bool passed = (tMeasuredMicros > (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5));
+#if defined(LOCAL_TRACE)
+ if (passed) {
+ Serial.println(F(" => passed"));
+ } else {
+ Serial.println(F(" => FAILED"));
+ }
+#endif
+ return passed;
+}
+bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
+ return matchTicks(measured_ticks, desired_us);
}
/**
@@ -1191,29 +1409,43 @@ bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
* @return true, if values match
*/
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
-#if defined(LOCAL_TRACE)
- Serial.print(F("Testing mark (actual vs desired): "));
- Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
- Serial.print(F("us vs "));
- Serial.print(aMatchValueMicros, DEC);
- Serial.print(F("us: "));
- Serial.print(TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
- Serial.print(F(" <= "));
- Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
- Serial.print(F(" <= "));
- Serial.print(TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
-#endif
- // compensate for marks exceeded by demodulator hardware
- bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS))
- && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS)));
-#if defined(LOCAL_TRACE)
- if (passed) {
- Serial.println(F(" => passed"));
- } else {
- Serial.println(F(" => FAILED"));
- }
+#if (MARK_EXCESS_MICROS == 0)
+ return matchTicks(aMeasuredTicks, aMatchValueMicros);
+#else
+
+# if !defined(USE_OLD_MATCH_FUNCTIONS)
+ return matchTicks(aMeasuredTicks, aMatchValueMicros, -MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors
+# endif
+
+ // old version here
+ aMatchValueMicros += MARK_EXCESS_MICROS;
+# if defined(LOCAL_TRACE)
+ Serial.print(F("Testing mark (actual vs desired): "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F("us vs "));
+ Serial.print(aMatchValueMicros);
+ Serial.print(F("us: "));
+// Serial.print(F("TICKS_LOW="));
+// Serial.print(TICKS_LOW(aMatchValueMicros));
+// Serial.print(F(" "));
+ Serial.print(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK);
+# endif
+ // compensate for marks exceeded by demodulator hardware
+ bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros))
+ && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
+# if defined(LOCAL_TRACE)
+ if (passed) {
+ Serial.println(F(" => passed"));
+ } else {
+ Serial.println(F(" => FAILED"));
+ }
+# endif
+ return passed;
#endif
- return passed;
}
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
@@ -1225,29 +1457,41 @@ bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
* @return true, if values match
*/
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
-#if defined(LOCAL_TRACE)
- Serial.print(F("Testing space (actual vs desired): "));
- Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
- Serial.print(F("us vs "));
- Serial.print(aMatchValueMicros, DEC);
- Serial.print(F("us: "));
- Serial.print(TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
- Serial.print(F(" <= "));
- Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
- Serial.print(F(" <= "));
- Serial.print(TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
-#endif
- // compensate for spaces shortened by demodulator hardware
- bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS))
- && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS)));
-#if defined(LOCAL_TRACE)
- if (passed) {
- Serial.println(F(" => passed"));
- } else {
- Serial.println(F(" => FAILED"));
- }
+#if (MARK_EXCESS_MICROS == 0)
+ return matchTicks(aMeasuredTicks, aMatchValueMicros);
+#else
+# if !defined(USE_OLD_MATCH_FUNCTIONS)
+ return matchTicks(aMeasuredTicks, aMatchValueMicros, MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors
+# endif
+ // old version here
+ aMatchValueMicros -= MARK_EXCESS_MICROS;
+# if defined(LOCAL_TRACE)
+ Serial.print(F("Testing space (actual vs desired): "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F("us vs "));
+ Serial.print(aMatchValueMicros);
+ Serial.print(F("us: "));
+ Serial.print(F("LOW="));
+ Serial.print(TICKS_LOW(aMatchValueMicros));
+ Serial.print(F(" "));
+ Serial.print(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(aMeasuredTicks * MICROS_PER_TICK);
+ Serial.print(F(" <= "));
+ Serial.print(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK);
+# endif
+ // compensate for spaces shortened by demodulator hardware
+ bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros))
+ && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
+# if defined(LOCAL_TRACE)
+ if (passed) {
+ Serial.println(F(" => passed"));
+ } else {
+ Serial.println(F(" => FAILED"));
+ }
+# endif
+ return passed;
#endif
- return passed;
}
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) {
@@ -1261,8 +1505,8 @@ int getMarkExcessMicros() {
return MARK_EXCESS_MICROS;
}
-/*
- * Check if protocol is not detected and detected space between two transmissions
+/**
+ * Checks if protocol is not detected and detected space between two transmissions
* is smaller than known value for protocols (Sony with around 24 ms)
* @return true, if CheckForRecordGapsMicros() has printed a message, i.e. gap < 15ms (RECORD_GAP_MICROS_WARNING_THRESHOLD)
*/
@@ -1295,87 +1539,367 @@ void IRrecv::printActiveIRProtocols(Print *aSerial) {
// call no class function with same name
::printActiveIRProtocols(aSerial);
}
+/*
+ * Prints a list of enabled protocols for this application.
+ * @param aSerial pointer to serial used for printing. Use "&Serial".
+ */
void printActiveIRProtocols(Print *aSerial) {
#if defined(DECODE_ONKYO)
- aSerial->print(F("Onkyo, "));
+ aSerial->print(F("Onkyo, "));
#elif defined(DECODE_NEC)
- aSerial->print(F("NEC/NEC2/Onkyo/Apple, "));
+ aSerial->print(F("NEC/NEC2/Onkyo/Apple, "));
#endif
#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
- aSerial->print(F("Panasonic/Kaseikyo, "));
+ aSerial->print(F("Panasonic/Kaseikyo, "));
#endif
#if defined(DECODE_DENON)
- aSerial->print(F("Denon/Sharp, "));
+ aSerial->print(F("Denon/Sharp, "));
#endif
#if defined(DECODE_SONY)
- aSerial->print(F("Sony, "));
+ aSerial->print(F("Sony, "));
#endif
#if defined(DECODE_RC5)
- aSerial->print(F("RC5, "));
+ aSerial->print(F("RC5, "));
#endif
#if defined(DECODE_RC6)
- aSerial->print(F("RC6, "));
+ aSerial->print(F("RC6, "));
#endif
#if defined(DECODE_LG)
- aSerial->print(F("LG, "));
+ aSerial->print(F("LG, "));
#endif
#if defined(DECODE_JVC)
- aSerial->print(F("JVC, "));
+ aSerial->print(F("JVC, "));
#endif
#if defined(DECODE_SAMSUNG)
- aSerial->print(F("Samsung, "));
+ aSerial->print(F("Samsung, "));
#endif
/*
* Start of the exotic protocols
*/
#if defined(DECODE_BEO)
- aSerial->print(F("Bang & Olufsen, "));
+ aSerial->print(F("Bang & Olufsen, "));
#endif
#if defined(DECODE_FAST)
- aSerial->print(F("FAST, "));
+ aSerial->print(F("FAST, "));
#endif
#if defined(DECODE_WHYNTER)
- aSerial->print(F("Whynter, "));
+ aSerial->print(F("Whynter, "));
#endif
#if defined(DECODE_LEGO_PF)
- aSerial->print(F("Lego Power Functions, "));
+ 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, "));
+ aSerial->print(F("MagiQuest, "));
#endif
#if defined(DECODE_DISTANCE_WIDTH)
- aSerial->print(F("Universal Pulse Distance Width, "));
+ aSerial->print(F("Universal Pulse Distance Width, "));
#endif
#if defined(DECODE_HASH)
- aSerial->print(F("Hash "));
+ aSerial->print(F("Hash "));
#endif
#if defined(NO_DECODER) // for sending raw only
- (void)aSerial; // to avoid compiler warnings
+ (void)aSerial; // to avoid compiler warnings
#endif
}
+/** @}
+ * \addtogroup Print Print functions
+ * @{
+ */
+
/**
* Function to print values and flags of IrReceiver.decodedIRData in one line.
* Ends with println().
*
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
- * @param aPrintRepeatGap If true also print the gap before repeats.
* @param aCheckForRecordGapsMicros If true, call CheckForRecordGapsMicros() which may do a long printout,
* which in turn may block the proper detection of repeats.*
* @return true, if CheckForRecordGapsMicros() has printed a message, i.e. gap < 15ms (RECORD_GAP_MICROS_WARNING_THRESHOLD).
*/
bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
+ // DEPRECATED
+ (void) aPrintRepeatGap;
+ return printIRResultShort(aSerial, aCheckForRecordGapsMicros);
+}
+bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) {
+
+ uint8_t tFlags = decodedIRData.flags;
+ if (tFlags & IRDATA_FLAGS_WAS_OVERFLOW) {
+ aSerial->println(F("Overflow"));
+ } else {
+ aSerial->print(F("Protocol="));
+ aSerial->print(getProtocolString());
+ if (decodedIRData.protocol == UNKNOWN) {
+#if defined(DECODE_HASH)
+ aSerial->print(F(" Hash=0x"));
+#if (__INT_WIDTH__ < 32)
+ aSerial->print(decodedIRData.decodedRawData, HEX);
+#else
+ PrintULL::print(aSerial,decodedIRData.decodedRawData, HEX);
+#endif
+
+#endif
+#if !defined(DISABLE_CODE_FOR_RECEIVER)
+ aSerial->print(' ');
+ aSerial->print((decodedIRData.rawlen + 1) / 2);
+ aSerial->println(F(" bits (incl. gap and start) received"));
+#endif
+ } else {
+#if defined(DECODE_DISTANCE_WIDTH)
+ if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) {
+#endif
+ /*
+ * New decoders have address and command
+ */
+ aSerial->print(F(" Address=0x"));
+ aSerial->print(decodedIRData.address, HEX);
+
+ aSerial->print(F(", Command=0x"));
+ aSerial->print(decodedIRData.command, HEX);
+
+ if (tFlags & IRDATA_FLAGS_EXTRA_INFO) {
+ aSerial->print(F(", Extra=0x"));
+ aSerial->print(decodedIRData.extra, HEX);
+ }
+
+ if (tFlags & IRDATA_FLAGS_PARITY_FAILED) {
+ aSerial->print(F(", Parity fail"));
+ }
+
+ if (tFlags & IRDATA_FLAGS_TOGGLE_BIT) {
+ aSerial->print(F(", Toggle=1"));
+ }
+#if defined(DECODE_DISTANCE_WIDTH)
+ }
+#endif
+
+ /*
+ * Print raw data, numberOfBits and MSB or LSB
+ */
+ if (!(tFlags & IRDATA_FLAGS_IS_REPEAT) || decodedIRData.decodedRawData != 0) {
+ aSerial->print(F(", Raw-Data=0x"));
+#if (__INT_WIDTH__ < 32)
+ aSerial->print(decodedIRData.decodedRawData, HEX);
+#else
+ PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
+#endif
+ aSerial->print(F(", "));
+
+ /*
+ * Print number of bits processed
+ */
+ aSerial->print(decodedIRData.numberOfBits);
+ aSerial->print(F(" bits,"));
+
+ if (tFlags & IRDATA_FLAGS_IS_MSB_FIRST) {
+ aSerial->print(F(" MSB first"));
+ } else {
+ aSerial->print(F(" LSB first"));
+ }
+ }
+
+ /*
+ * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
+ */
+ if (tFlags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
+ aSerial->print(F(", "));
+ if (tFlags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
+ aSerial->print(F("Auto-"));
+ }
+ aSerial->print(F("Repeat"));
+ }
+#if !defined(DISABLE_CODE_FOR_RECEIVER)
+ aSerial->print(F(", Gap="));
+ aSerial->print((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK);
+ aSerial->print(F("us"));
+
+ /*
+ * Print complete duration of IR frame
+ */
+ uint16_t tSumOfDurationTicks = 0;
+ for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
+ tSumOfDurationTicks += irparams.rawbuf[i];
+ }
+ aSerial->print(F(", Duration="));
+ aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
+ aSerial->println(F("us"));
+#else
+ aSerial->println();
+#endif
+ }
+ }
+
// call no class function with same name
- ::printIRResultShort(aSerial, &decodedIRData, aPrintRepeatGap);
if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) {
return checkForRecordGapsMicros(aSerial);
}
return false;
}
+/*
+ * Only used in example ReceiveAndSend.cpp
+ */
+void printIRDataShort(Print *aSerial, IRData *aIRDataPtr) {
+
+ aSerial->print(F("Protocol="));
+ aSerial->print(getProtocolString(aIRDataPtr->protocol));
+#if defined(DECODE_DISTANCE_WIDTH)
+ if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
+#endif
+ /*
+ * New decoders have address and command
+ */
+ aSerial->print(F(" Address=0x"));
+ aSerial->print(aIRDataPtr->address, HEX);
+
+ aSerial->print(F(" Command=0x"));
+ aSerial->print(aIRDataPtr->command, HEX);
+
+#if defined(DECODE_DISTANCE_WIDTH)
+ }
+#endif
+
+ /*
+ * Print number of bits
+ */
+ aSerial->print(' ');
+ aSerial->print(aIRDataPtr->numberOfBits, DEC);
+ aSerial->print(F(" bits"));
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
+ aSerial->print(F(" MSB first"));
+ } else {
+ aSerial->print(F(" LSB first"));
+ }
+
+ /*
+ * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
+ */
+ if (aIRDataPtr->flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
+ aSerial->print(' ');
+ if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
+ aSerial->print(F("Auto-"));
+ }
+ aSerial->print(F("Repeat"));
+ }
+ aSerial->println();
+}
+
+/**
+ * Deprecated static function to be able to print data to send or copied received data.
+ * Ends with println().
+ *
+ * @param aSerial The Print object on which to write, for Arduino you can use &Serial.
+ * @param aIRDataPtr Pointer to the data to be printed.
+ * @param aPrintRepeatGap If true also print the gap before repeats.
+ *
+ */
+void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) {
+ // DEPRECATED
+
+ (void) aPrintRepeatGap;
+ printIRDataShort(aSerial, aIRDataPtr);
+}
+void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) {
+ // DEPRECATED
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) {
+ aSerial->println(F("Overflow"));
+ return;
+ }
+ aSerial->print(F("Protocol="));
+ aSerial->print(getProtocolString(aIRDataPtr->protocol));
+ if (aIRDataPtr->protocol == UNKNOWN) {
+#if defined(DECODE_HASH)
+ aSerial->print(F(" Hash=0x"));
+#if (__INT_WIDTH__ < 32)
+ aSerial->print(aIRDataPtr->decodedRawData, HEX);
+#else
+ PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX);
+#endif
+
+#endif
+#if !defined(DISABLE_CODE_FOR_RECEIVER)
+ aSerial->print(' ');
+ aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC);
+ aSerial->println(F(" bits (incl. gap and start) received"));
+#endif
+ } else {
+#if defined(DECODE_DISTANCE_WIDTH)
+ if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
+#endif
+ /*
+ * New decoders have address and command
+ */
+ aSerial->print(F(" Address=0x"));
+ aSerial->print(aIRDataPtr->address, HEX);
+
+ aSerial->print(F(" Command=0x"));
+ aSerial->print(aIRDataPtr->command, HEX);
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
+ aSerial->print(F(" Extra=0x"));
+ aSerial->print(aIRDataPtr->extra, HEX);
+ }
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_PARITY_FAILED) {
+ aSerial->print(F(" Parity fail"));
+ }
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_TOGGLE_BIT) {
+ aSerial->print(F(" Toggle=1"));
+ }
+#if defined(DECODE_DISTANCE_WIDTH)
+ }
+#endif
+
+ /*
+ * Print raw data
+ */
+ if (!(aIRDataPtr->flags & IRDATA_FLAGS_IS_REPEAT) || aIRDataPtr->decodedRawData != 0) {
+ aSerial->print(F(" Raw-Data=0x"));
+#if (__INT_WIDTH__ < 32)
+ aSerial->print(aIRDataPtr->decodedRawData, HEX);
+#else
+ PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX);
+#endif
+ /*
+ * Print number of bits processed
+ */
+ aSerial->print(' ');
+ aSerial->print(aIRDataPtr->numberOfBits, DEC);
+ aSerial->print(F(" bits"));
+
+ if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
+ aSerial->print(F(" MSB first"));
+ } else {
+ aSerial->print(F(" LSB first"));
+ }
+ }
+
+ /*
+ * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
+ */
+ if (aIRDataPtr->flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
+ aSerial->print(' ');
+ if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
+ aSerial->print(F("Auto-"));
+ }
+ aSerial->print(F("Repeat"));
+ }
+#if !defined(DISABLE_CODE_FOR_RECEIVER)
+ aSerial->print(F(" Gap="));
+ aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK);
+ aSerial->println(F("us"));
+#else
+ aSerial->println();
+#endif
+ }
+}
+
void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo) {
aSerial->print(aDistanceWidthTimingInfo->HeaderMarkMicros);
aSerial->print(F(", "));
@@ -1397,7 +1921,7 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf
uint8_t IRrecv::getMaximumMarkTicksFromRawData() {
uint8_t tMaximumTick = 0;
for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
- auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tTick = irparams.rawbuf[i];
if (tMaximumTick < tTick) {
tMaximumTick = tTick;
}
@@ -1407,7 +1931,7 @@ uint8_t IRrecv::getMaximumMarkTicksFromRawData() {
uint8_t IRrecv::getMaximumSpaceTicksFromRawData() {
uint8_t tMaximumTick = 0;
for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
- auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tTick = irparams.rawbuf[i];
if (tMaximumTick < tTick) {
tMaximumTick = tTick;
}
@@ -1427,7 +1951,7 @@ uint8_t IRrecv::getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark) {
i = 3;
}
for (; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
- auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tTick = irparams.rawbuf[i];
if (tMaximumTick < tTick) {
tMaximumTick = tTick;
}
@@ -1439,11 +1963,13 @@ uint32_t IRrecv::getTotalDurationOfRawData() {
uint16_t tSumOfDurationTicks = 0;
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
- tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i];
+ tSumOfDurationTicks += irparams.rawbuf[i];
}
return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK;
}
+// @formatter:off
+
/**
* Function to print values and flags of IrReceiver.decodedIRData in one line.
* do not print for repeats except IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT.
@@ -1453,9 +1979,19 @@ uint32_t IRrecv::getTotalDurationOfRawData() {
* @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_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00
|| (decodedIRData.flags & IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT))) {
+
+ /*
+ * Generating the string:
+ * Send on a 8 bit platform with:
+ * uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
+ * IrSender.send
+ * or
+ * Send on a 8 bit platform with: IrSender.send
+ * or
+ * Send with: IrSender.send
+ */
#if defined(DECODE_DISTANCE_WIDTH)
uint_fast8_t tNumberOfArrayData = 0;
if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) {
@@ -1464,18 +2000,16 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1;
if(tNumberOfArrayData > 1) {
aSerial->println();
- aSerial->print(F(" uint32_t tRawData[]={0x"));
+ aSerial->print(F(" uint32_t tRawData[]={0x"));
+ for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
+ aSerial->print(decodedIRData.decodedRawDataArray[i], HEX);
# else
- aSerial->print(F("Send on a 32 bit platform with: "));
+ aSerial->print(F("Send on a 32 bit platform with: "));
tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1;
if(tNumberOfArrayData > 1) {
aSerial->println();
- aSerial->print(F(" uint64_t tRawData[]={0x"));
-# endif
+ aSerial->print(F(" uint64_t tRawData[]={0x"));
for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
-# if (__INT_WIDTH__ < 32)
- aSerial->print(decodedIRData.decodedRawDataArray[i], HEX);
-# else
PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX);
# endif
if (i != tNumberOfArrayData - 1) {
@@ -1483,58 +2017,46 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
}
}
aSerial->println(F("};"));
- aSerial->print(F(" "));
+ aSerial->print(F(" "));
}
- } else {
+ } else { // if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH)
aSerial->print(F("Send with: "));
}
+ if (decodedIRData.protocol == UNKNOWN){
+ aSerial->println();
+ aSerial->print(F(" "));
+ printIRResultAsCArray(&Serial);
+ aSerial->print(F(" "));
+ }
aSerial->print(F("IrSender.send"));
#else
aSerial->print(F("Send with: IrSender.send"));
-#endif
+#endif // #if defined(DECODE_DISTANCE_WIDTH)
-#if defined(DECODE_DISTANCE_WIDTH)
- if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) {
-#endif
- aSerial->print(getProtocolString());
- aSerial->print(F("(0x"));
-#if defined(DECODE_MAGIQUEST)
- if (decodedIRData.protocol == MAGIQUEST) {
-# if (__INT_WIDTH__ < 32)
- aSerial->print(decodedIRData.decodedRawData, HEX);
-# else
- PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
-# endif
- } else {
- aSerial->print(decodedIRData.address, HEX);
- }
-#else
/*
- * New decoders have address and command
+ * Generating the string:
+ * Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, ,
+ * or
+ * PulseDistanceWidth(38, 550, 1250, 500, 1250, 1300, 400, 0x3D9EAC, 23, PROTOCOL_IS_LSB_FIRST, , );
+ * or
+ * PulseDistanceWidthFromArray(38, 8900, 4350, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , );
+ * or
+ * (0x, 0x, );
*/
- 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(", "));
+ if (decodedIRData.protocol == UNKNOWN){
+ aSerial->print(F("Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, , "));
}
-
#if defined(DECODE_DISTANCE_WIDTH)
- } else {
+ else if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) {
/*
* Pulse distance or pulse width here
*/
- aSerial->print("PulseDistanceWidth");
+ aSerial->print(F("PulseDistanceWidth"));
if(tNumberOfArrayData > 1) {
- aSerial->print("FromArray(38, ");
+ aSerial->print(F("FromArray(38, "));
} else {
- aSerial->print("(38, ");
+ aSerial->print(F("(38, "));
}
printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo);
@@ -1549,7 +2071,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
# endif
aSerial->print(F(", "));
}
- aSerial->print(decodedIRData.numberOfBits);// aNumberOfBits
+ aSerial->print(decodedIRData.numberOfBits); // aNumberOfBits
aSerial->print(F(", PROTOCOL_IS_"));
if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) {
@@ -1559,9 +2081,43 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
}
aSerial->print(F("SB_FIRST, , "));
}
+#endif // defined(DECODE_DISTANCE_WIDTH)
+ else {
+ /*
+ * Regular protocols here
+ */
+ aSerial->print(getProtocolString());
+ aSerial->print(F("(0x"));
+#if defined(DECODE_MAGIQUEST)
+ if (decodedIRData.protocol == MAGIQUEST) {
+# if (__INT_WIDTH__ < 32)
+ aSerial->print(decodedIRData.decodedRawData, HEX);
+# else
+ PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
+# endif
+ } else {
+ aSerial->print(decodedIRData.address, HEX);
+ }
+#else
+ /*
+ * New decoders have address and command
+ */
+ aSerial->print(decodedIRData.address, HEX);
#endif
-#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
- if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && decodedIRData.protocol == KASEIKYO) {
+
+ 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(", "));
+ }
+ }
+
+#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6)
+ if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A)) {
+ // Vendor code parameter, which is after numberOfRepeats parameter
aSerial->print(F(", 0x"));
aSerial->print(decodedIRData.extra, HEX);
}
@@ -1571,6 +2127,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) {
}
}
+// @formatter:on
/**
* Function to print protocol number, address, command, raw data and repeat flag of IrReceiver.decodedIRData in one short line.
* Does not print a Newline / does not end with println().
@@ -1582,15 +2139,15 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
aSerial->print(decodedIRData.protocol);
if (decodedIRData.protocol == UNKNOWN) {
#if defined(DECODE_HASH)
- aSerial->print(F(" #=0x"));
+ aSerial->print(F(" #=0x"));
# if (__INT_WIDTH__ < 32)
- aSerial->print(decodedIRData.decodedRawData, HEX);
+ aSerial->print(decodedIRData.decodedRawData, HEX);
# else
- PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
+ PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
# endif
#endif
aSerial->print(' ');
- aSerial->print((decodedIRData.rawlen + 1) / 2, DEC);
+ aSerial->print((decodedIRData.rawlen + 1) / 2);
aSerial->println(F(" bits received"));
} else {
/*
@@ -1606,7 +2163,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
#if (__INT_WIDTH__ < 32)
aSerial->print(decodedIRData.decodedRawData, HEX);
#else
- PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
+ PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
#endif
if (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) {
@@ -1615,8 +2172,27 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
}
}
+/*
+ * Not used yet
+ */
+void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
+ uint16_t tSumOfDurationTicks = 0;
+ for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
+ tSumOfDurationTicks += irparams.rawbuf[i];
+ }
+ aSerial->print(F("Duration="));
+ if (aOutputMicrosecondsInsteadOfTicks) {
+ aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
+ aSerial->println(F("us"));
+
+ } else {
+ aSerial->print(tSumOfDurationTicks);
+ aSerial->println(F(" ticks"));
+ }
+}
+
/**
- * Dump out the timings in IrReceiver.decodedIRData.rawDataPtr->rawbuf[] array 8 values per line.
+ * Dump out the timings in IrReceiver.irparams.rawbuf[] array 8 values per line.
*
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
* @param aOutputMicrosecondsInsteadOfTicks Output the (rawbuf_values * MICROS_PER_TICK) for better readability.
@@ -1624,8 +2200,8 @@ void IRrecv::printIRResultMinimal(Print *aSerial) {
void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
// Print Raw data
- aSerial->print(F("rawData["));
- aSerial->print(decodedIRData.rawlen, DEC);
+ aSerial->print(F("rawIRTimings["));
+ aSerial->print(decodedIRData.rawlen);
aSerial->println(F("]: "));
/*
@@ -1633,9 +2209,9 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
*/
aSerial->print(F(" -"));
if (aOutputMicrosecondsInsteadOfTicks) {
- aSerial->println((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK, DEC);
+ aSerial->println((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK);
} else {
- aSerial->println(decodedIRData.initialGapTicks, DEC);
+ aSerial->println(decodedIRData.initialGapTicks);
}
// Newline is printed every 8. value, if tCounterForNewline % 8 == 0
@@ -1643,22 +2219,22 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
// check if we have a protocol with no or 8 start bits
#if defined(DECODE_DENON) || defined(DECODE_MAGIQUEST)
- if (
+ if (
# if defined(DECODE_DENON)
- decodedIRData.protocol == DENON || decodedIRData.protocol == SHARP ||
+ decodedIRData.protocol == DENON || decodedIRData.protocol == SHARP ||
# endif
# if defined(DECODE_MAGIQUEST)
- decodedIRData.protocol == MAGIQUEST ||
+ decodedIRData.protocol == MAGIQUEST ||
# endif
- false) {
- tCounterForNewline = 0; // no or 8 start bits
- }
+ false) {
+ tCounterForNewline = 0; // no or 8 start bits
+ }
#endif
uint32_t tDuration;
uint16_t tSumOfDurationTicks = 0;
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
- auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tCurrentTicks = irparams.rawbuf[i];
if (aOutputMicrosecondsInsteadOfTicks) {
tDuration = tCurrentTicks * MICROS_PER_TICK;
} else {
@@ -1682,7 +2258,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
if (tDuration < 10) {
aSerial->print(' ');
}
- aSerial->print(tDuration, DEC);
+ aSerial->print(tDuration);
if ((i & 1) && (i + 1) < decodedIRData.rawlen) {
aSerial->print(','); //',' not required for last one
@@ -1695,45 +2271,56 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI
}
aSerial->println();
- aSerial->print("Sum: ");
+ aSerial->print(F("Duration="));
if (aOutputMicrosecondsInsteadOfTicks) {
- aSerial->println((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC);
+ aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
+ aSerial->println(F("us"));
+
} else {
- aSerial->println(tSumOfDurationTicks, DEC);
+ aSerial->print(tSumOfDurationTicks);
+ aSerial->println(F(" ticks"));
}
+ aSerial->println();
+
}
/**
- * Dump out the IrReceiver.decodedIRData.rawDataPtr->rawbuf[] to be used as C definition for sendRaw().
+ * Dump out the IrReceiver.irparams.rawbuf[] to be used as C definition for sendRaw().
+ *
*
- * Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
* Print ticks in 8 bit format to save space.
* Maximum is 255*50 microseconds = 12750 microseconds = 12.75 ms, which hardly ever occurs inside an IR sequence.
* Recording of IRremote anyway stops at a gap of RECORD_GAP_MICROS (5 ms).
*
- * @param aSerial The Print object on which to write, for Arduino you can use &Serial.
- * @param aOutputMicrosecondsInsteadOfTicks Output the (rawbuf_values * MICROS_PER_TICK) for better readability.
+ * @param aSerial The Print object on which to write, for Arduino you can use &Serial.
+ * @param aOutputMicrosecondsInsteadOfTicks Output the (rawbuf_values * MICROS_PER_TICK) for better readability.
+ * @param aDoCompensate Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding!
*/
void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
+ printIRResultAsCArray(aSerial, aOutputMicrosecondsInsteadOfTicks, true);
+}
+void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks, bool aDoCompensate) {
// Start declaration
if (aOutputMicrosecondsInsteadOfTicks) {
- aSerial->print(F("uint16_t rawData[")); // variable type, array name
+ aSerial->print(F("uint16_t rawIRTimings[")); // variable type, array name
} else {
aSerial->print(F("uint8_t rawTicks[")); // variable type, array name
}
- aSerial->print(decodedIRData.rawlen - 1, DEC); // array size
+ aSerial->print(decodedIRData.rawlen - 1); // array size
aSerial->print(F("] = {")); // Start declaration
// Dump data
for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
- uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
+ uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK;
- if (i & 1) {
- // Mark
- tDuration -= MARK_EXCESS_MICROS;
- } else {
- tDuration += MARK_EXCESS_MICROS;
+ if (aDoCompensate) {
+ if (i & 1) {
+ // Mark
+ tDuration -= MARK_EXCESS_MICROS;
+ } else {
+ tDuration += MARK_EXCESS_MICROS;
+ }
}
if (aOutputMicrosecondsInsteadOfTicks) {
@@ -1756,15 +2343,12 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr
// Comment
aSerial->print(F(" // "));
printIRResultShort(aSerial);
-
-// Newline
- aSerial->println("");
}
/**
* Store the decodedIRData to be used for sendRaw().
*
- * Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding and store it in an array provided.
+ * Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding and store it in an array.
*
* Maximum for uint8_t is 255*50 microseconds = 12750 microseconds = 12.75 ms, which hardly ever occurs inside an IR sequence.
* Recording of IRremote anyway stops at a gap of RECORD_GAP_MICROS (5 ms).
@@ -1775,7 +2359,7 @@ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) {
// Store data, skip leading space#
IRRawlenType i;
for (i = 1; i < decodedIRData.rawlen; i++) {
- uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
+ uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK;
if (i & 1) {
// Mark
tDuration -= MARK_EXCESS_MICROS;
@@ -1791,6 +2375,9 @@ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) {
/**
* Print results as C variables to be used for sendXXX()
+ * uint16_t address = 0x44;
+ * uint16_t command = 0x11;
+ * uint32_t rawData = 0x44BB11EE;
* @param aSerial The Print object on which to write, for Arduino you can use &Serial.
*/
void IRrecv::printIRResultAsCVariables(Print *aSerial) {
@@ -1812,17 +2399,16 @@ void IRrecv::printIRResultAsCVariables(Print *aSerial) {
// All protocols have raw data
#if __INT_WIDTH__ < 32
- aSerial->print(F("uint32_t rawData = 0x"));
+ aSerial->print(F("uint32_t rawIRTimings = 0x"));
#else
- aSerial->print(F("uint64_t rawData = 0x"));
+ aSerial->print(F("uint64_t rawIRTimings = 0x"));
#endif
#if (__INT_WIDTH__ < 32)
aSerial->print(decodedIRData.decodedRawData, HEX);
#else
- PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
+ PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
#endif
aSerial->println(';');
- aSerial->println();
}
}
@@ -1832,10 +2418,10 @@ const __FlashStringHelper* IRrecv::getProtocolString() {
return ::getProtocolString(decodedIRData.protocol);
}
#else
-const char* IRrecv::getProtocolString() {
- // call no class function with same name
- return ::getProtocolString(decodedIRData.protocol);
-}
+ const char* IRrecv::getProtocolString() {
+ // call no class function with same name
+ return ::getProtocolString(decodedIRData.protocol);
+ }
#endif
/**********************************************************************************************************************
@@ -1869,66 +2455,66 @@ bool IRrecv::decode_old(decode_results *aResults) {
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; // for print
#if defined(DECODE_NEC)
- IR_DEBUG_PRINTLN(F("Attempting old NEC decode"));
- if (decodeNECMSB(aResults)) {
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting old NEC decode"));
+ if (decodeNECMSB(aResults)) {
+ return true;
+ }
#endif
#if defined(DECODE_SONY)
- IR_DEBUG_PRINTLN(F("Attempting old Sony decode"));
- if (decodeSonyMSB(aResults)) {
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting old Sony decode"));
+ if (decodeSonyMSB(aResults)) {
+ return true;
+ }
#endif
#if defined(DECODE_RC5)
- IR_DEBUG_PRINTLN(F("Attempting RC5 decode"));
- if (decodeRC5()) {
- aResults->bits = decodedIRData.numberOfBits;
- aResults->value = decodedIRData.decodedRawData;
- aResults->decode_type = RC5;
+ IR_DEBUG_PRINTLN(F("Attempting RC5 decode"));
+ if (decodeRC5()) {
+ aResults->bits = decodedIRData.numberOfBits;
+ aResults->value = decodedIRData.decodedRawData;
+ aResults->decode_type = RC5;
- return true;
- }
+ return true;
+ }
#endif
#if defined(DECODE_RC6)
- IR_DEBUG_PRINTLN(F("Attempting RC6 decode"));
- if (decodeRC6()) {
- aResults->bits = decodedIRData.numberOfBits;
- aResults->value = decodedIRData.decodedRawData;
- aResults->decode_type = RC6;
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting RC6 decode"));
+ if (decodeRC6()) {
+ aResults->bits = decodedIRData.numberOfBits;
+ aResults->value = decodedIRData.decodedRawData;
+ aResults->decode_type = RC6;
+ return true;
+ }
#endif
// Removed bool IRrecv::decodePanasonicMSB(decode_results *aResults) since implementations was wrong (wrong length), and nobody recognized it
#if defined(DECODE_LG)
- IR_DEBUG_PRINTLN(F("Attempting old LG decode"));
- if (decodeLGMSB(aResults)) {return true;}
+ IR_DEBUG_PRINTLN(F("Attempting old LG decode"));
+ if (decodeLGMSB(aResults)) {return true;}
#endif
#if defined(DECODE_JVC)
- IR_DEBUG_PRINTLN(F("Attempting old JVC decode"));
- if (decodeJVCMSB(aResults)) {
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting old JVC decode"));
+ if (decodeJVCMSB(aResults)) {
+ return true;
+ }
#endif
#if defined(DECODE_SAMSUNG)
- IR_DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
- if (decodeSAMSUNG(aResults)) {
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
+ if (decodeSAMSUNG(aResults)) {
+ return true;
+ }
#endif
#if defined(DECODE_DENON)
- IR_DEBUG_PRINTLN(F("Attempting old Denon decode"));
- if (decodeDenonOld(aResults)) {
- return true;
- }
+ IR_DEBUG_PRINTLN(F("Attempting old Denon decode"));
+ if (decodeDenonOld(aResults)) {
+ return true;
+ }
#endif
// decodeHash returns a hash on any input.
diff --git a/src/IRSend.hpp b/src/IRSend.hpp
index 470c64790..121e5ca2d 100644
--- a/src/IRSend.hpp
+++ b/src/IRSend.hpp
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2009-2023 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
+ * Copyright (c) 2009-2025 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@
#ifndef _IR_SEND_HPP
#define _IR_SEND_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -57,6 +57,10 @@
#define sendPin IR_SEND_PIN
#endif
+#if !defined(NO_LED_SEND_FEEDBACK_CODE)
+#define LED_SEND_FEEDBACK_CODE // Resolve the double negative
+#endif
+
/** \addtogroup Sending Sending IR data for multiple protocols
* @{
*/
@@ -68,50 +72,32 @@ IRsend::IRsend() { // @suppress("Class members should be properly initialized")
#if !defined(IR_SEND_PIN)
sendPin = 0;
#endif
-
-#if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
-#endif
}
+/******************************************************************************************************************
+ * LED feedback is always enabled for sending. It can only be disabled by using the macro NO_LED_SEND_FEEDBACK_CODE
+ *****************************************************************************************************************/
#if defined(IR_SEND_PIN)
/**
- * Only required to set LED feedback
- * Simple start with defaults - LED feedback enabled! Used if IR_SEND_PIN is defined. Saves program memory.
+ * Simple start with defaults. Used if IR_SEND_PIN is defined. Saves program memory.
*/
void IRsend::begin(){
-# if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
-# endif
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
#endif
}
/**
- * Only required to set LED feedback
- * @param aEnableLEDFeedback If true / ENABLE_LED_FEEDBACK, the feedback LED is activated while receiving or sending a PWM signal /a mark
- * @param aFeedbackLEDPin If 0 / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
+ * Only required to set LED feedback pin
+ * @param aFeedbackLEDPin If USE_DEFAULT_FEEDBACK_LED_PIN / 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
*/
-void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
-#if !defined(NO_LED_FEEDBACK_CODE)
- uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
- if(aEnableLEDFeedback) {
- tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
- }
- setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
-#else
- (void) aEnableLEDFeedback;
- (void) aFeedbackLEDPin;
-#endif
+void IRsend::begin(uint_fast8_t aFeedbackLEDPin) {
+ setLEDFeedbackPin(aFeedbackLEDPin);
}
#else // defined(IR_SEND_PIN)
IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be properly initialized")
sendPin = aSendPin;
-# if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK);
-# endif
}
/**
@@ -120,9 +106,6 @@ IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be pr
*/
void IRsend::begin(uint_fast8_t aSendPin) {
sendPin = aSendPin;
-# if !defined(NO_LED_FEEDBACK_CODE)
- setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND);
-# endif
}
void IRsend::setSendPin(uint_fast8_t aSendPin) {
@@ -132,29 +115,29 @@ void IRsend::setSendPin(uint_fast8_t aSendPin) {
/**
* Initializes the send and feedback pin
* @param aSendPin The Arduino pin number, where a IR sender diode is connected.
- * @param aEnableLEDFeedback If true the feedback LED is activated while receiving or sending a PWM signal /a mark
* @param aFeedbackLEDPin If 0 / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions
*/
-void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
+void IRsend::begin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin) {
#if defined(IR_SEND_PIN)
(void) aSendPin; // for backwards compatibility
#else
sendPin = aSendPin;
#endif
-#if !defined(NO_LED_FEEDBACK_CODE)
- uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
- if (aEnableLEDFeedback) {
- tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND;
- }
- setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
+#if defined(LED_SEND_FEEDBACK_CODE)
+ setLEDFeedbackPin(aFeedbackLEDPin);
#else
- (void) aEnableLEDFeedback;
(void) aFeedbackLEDPin;
#endif
}
#endif // defined(IR_SEND_PIN)
+// Deprecated
+void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
+ (void) aEnableLEDFeedback;
+ begin(aSendPin, aFeedbackLEDPin);
+}
+
/**
* Interprets and sends a IRData structure.
* @param aIRSendData The values of protocol, address, command and repeat flag are taken for sending.
@@ -407,8 +390,12 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma
return 1;
}
+/**********************************************************************************************************************
+ * SendRaw functions
+ **********************************************************************************************************************/
+
/**
- * Function using an 16 byte microsecond timing array for every purpose.
+ * Sends a 16 byte microsecond timing array.
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
@@ -427,9 +414,35 @@ void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLe
}
}
}
+/*
+ * Version with repeat
+ * @param aRepeatPeriodMillis - Time between start of two frames. Thus independent from frame length.
+ */
+void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
+
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ unsigned long tStartOfFrameMillis = millis();
+ sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz);
+
+ 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.
+ */
+ if (aRepeatPeriodMillis > tCurrentFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tCurrentFrameDurationMillis);
+ }
+ }
+ }
+}
/**
- * Function using an 8 byte tick timing array to save program memory
+ * Sends an 8 byte tick timing array to save program memory.
* Raw data starts with a Mark. No leading space as in received timing data!
*/
void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
@@ -444,25 +457,53 @@ void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBu
mark(aBufferWithTicks[i] * MICROS_PER_TICK);
}
}
- IRLedOff(); // Always end with the LED off
+}
+void IRsend::sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
+
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ unsigned long tStartOfFrameMillis = millis();
+ sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz);
+
+ 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.
+ */
+ if (aRepeatPeriodMillis > tCurrentFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tCurrentFrameDurationMillis);
+ }
+ }
+ }
}
/**
* Function using an 16 byte microsecond timing array in FLASH for every purpose.
* Raw data starts with a Mark. No leading space as in received timing data!
*/
-void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer,
+void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer,
uint_fast8_t aIRFrequencyKilohertz) {
#if !defined(__AVR__)
- sendRaw(aBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
+ sendRaw(aPGMBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
#else
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
/*
* Raw data starts with a mark
*/
+# if defined(LOCAL_DEBUG)
+ // If the PROGMEM array is defined in the function, the C-compiler uses a wrong address :-(. sizeof() works.
+ Serial.print(F("aPGMBufferWithMicroseconds=0x"));
+ Serial.println((uint16_t)aPGMBufferWithMicroseconds,HEX);
+#endif
+
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
- auto duration = pgm_read_word(&aBufferWithMicroseconds[i]);
+ uint16_t duration = pgm_read_word(&aPGMBufferWithMicroseconds[i]);
+// uint16_t duration = pgm_read_word(aPGMBufferWithMicroseconds); // is equivalent for the compiler
if (i & 1) {
// Odd
space(duration);
@@ -482,20 +523,42 @@ void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t a
#endif
}
+void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer,
+ uint_fast8_t aIRFrequencyKilohertz, uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
+
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ unsigned long tStartOfFrameMillis = millis();
+ sendRaw_P(aPGMBufferWithMicroseconds, aLengthOfBuffer, aIRFrequencyKilohertz);
+
+ 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.
+ */
+ if (aRepeatPeriodMillis > tCurrentFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tCurrentFrameDurationMillis);
+ }
+ }
+ }
+}
+
/**
* 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) {
+void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) {
#if !defined(__AVR__)
- sendRaw(aBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
+ sendRaw(aPGMBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz); // Let the function work for non AVR platforms
#else
// Set IR carrier frequency
enableIROut(aIRFrequencyKilohertz);
- uint_fast16_t duration;
for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) {
- duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK;
+ uint16_t duration = pgm_read_byte(&aPGMBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK;
if (i & 1) {
// Odd
space(duration);
@@ -508,30 +571,184 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf
Serial.print(F("M="));
# endif
}
- }
- IRLedOff(); // Always end with the LED off
# if defined(LOCAL_DEBUG)
- Serial.println(duration);
+ Serial.println(duration);
# endif
+ }
#endif
}
+void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
+
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ unsigned long tStartOfFrameMillis = millis();
+ sendRaw_P(aPGMBufferWithTicks, aLengthOfBuffer, aIRFrequencyKilohertz);
+
+ 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.
+ */
+ if (aRepeatPeriodMillis > tCurrentFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tCurrentFrameDurationMillis);
+ }
+ }
+ }
+}
+/**********************************************************************************************************************
+ * Core send function
+ **********************************************************************************************************************/
/**
- * Sends PulseDistance data from array
- * 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.
+ * Sends PulseDistance data with timing parameters and flag parameters.
* 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. Stop bit is otherwise sent for all pulse distance protocols.
+ * @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. Stop bit is otherwise sent for all pulse distance protocols.
*/
-void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
- IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
- int_fast8_t aNumberOfRepeats) {
- sendPulseDistanceWidthFromArray(aFrequencyKHz, aDistanceWidthTimingInfo->HeaderMarkMicros,
- aDistanceWidthTimingInfo->HeaderSpaceMicros, aDistanceWidthTimingInfo->OneMarkMicros,
- aDistanceWidthTimingInfo->OneSpaceMicros, aDistanceWidthTimingInfo->ZeroMarkMicros,
- aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
- aNumberOfRepeats);
+void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros,
+ uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) {
+
+#if defined(LOCAL_DEBUG)
+ Serial.print(aData, HEX);
+ Serial.print('|');
+ Serial.println(aNumberOfBits);
+ Serial.flush();
+#endif
+
+ // For MSBFirst, send data from MSB to LSB until mask bit is shifted out
+ IRRawDataType tMask = 1ULL << (aNumberOfBits - 1);
+ for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
+ if (((aFlags & PROTOCOL_IS_MSB_MASK) && (aData & tMask)) || (!(aFlags & PROTOCOL_IS_MSB_MASK) && (aData & 1))) {
+#if defined(LOCAL_TRACE)
+ Serial.print('1');
+#endif
+ mark(aOneMarkMicros);
+ space(aOneSpaceMicros);
+ } else {
+#if defined(LOCAL_TRACE)
+ Serial.print('0');
+#endif
+ mark(aZeroMarkMicros);
+ space(aZeroSpaceMicros);
+ }
+ if (aFlags & PROTOCOL_IS_MSB_MASK) {
+ tMask >>= 1;
+ } else {
+ aData >>= 1;
+ }
+ }
+ /*
+ * Stop bit is sent for all pulse distance protocols i.e. aOneSpaceMicros != aZeroSpaceMicros.
+ * Therefore it is not sent for Sony :-)
+ * For sending from an array, no intermediate stop bit must be sent for all but last data chunk.
+ */
+ if ((!(aFlags & SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) {
+ // Send stop bit here
+#if defined(LOCAL_TRACE)
+ Serial.print('S');
+#endif
+ mark(aOneMarkMicros); // Use aOneMarkMicros for stop bits. This seems to be correct for all protocols :-)
+ }
+#if defined(LOCAL_TRACE)
+ Serial.println();
+#endif
+}
+
+/**********************************************************************************************************************
+ * Stubs for core send function with PulseDistanceWidthProtocolConstants parameter
+ **********************************************************************************************************************/
+
+/**
+ * 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) {
+
+ sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags);
+}
+
+void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData,
+ uint_fast8_t aNumberOfBits) {
+
+ PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
+ memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
+ sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
+ sendPulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aData, aNumberOfBits);
+}
+
+/**********************************************************************************************************************
+ * Send functions with detailed parameters
+ **********************************************************************************************************************/
+
+/**
+ * Sends PulseDistance frames and repeats.
+ * @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. 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 nullptr, 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, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
+ void (*aSpecialSendRepeatFunction)()) {
+
+ if (aNumberOfRepeats < 0) {
+ if (aSpecialSendRepeatFunction != nullptr) {
+ aSpecialSendRepeatFunction();
+ return;
+ } else {
+ aNumberOfRepeats = 0; // send a plain frame as repeat
+ }
+ }
+
+ // Set IR carrier frequency
+ enableIROut(aFrequencyKHz);
+
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ unsigned long tStartOfFrameMillis = millis();
+
+ if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != nullptr) {
+ // send special repeat
+ aSpecialSendRepeatFunction();
+ } else {
+ // Header and regular frame
+ mark(aHeaderMarkMicros);
+ space(aHeaderSpaceMicros);
+ sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits,
+ aFlags);
+ }
+
+ 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 (aRepeatPeriodMillis > tFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tFrameDurationMillis);
+ }
+ }
+ }
}
+
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,73 +814,61 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_
}
}
-/**
- * Sends PulseDistance data from array using PulseDistanceWidthProtocolConstants
- * 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) {
+void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
+ uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
+ int_fast8_t aNumberOfRepeats) {
-// Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
-// sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
-// aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
-// aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
-// aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
-// aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
-// aNumberOfRepeats);
// Set IR carrier frequency
- enableIROut(aProtocolConstants->FrequencyKHz);
+ enableIROut(aFrequencyKHz);
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
#if defined(LOCAL_DEBUG)
// fist data
Serial.print(F("Data[0]=0x"));
- Serial.print(aDecodedRawDataArray[0], HEX);
+ Serial.print(aDecodedRawDataPGMArray[0], HEX);
if (tNumberOf32Or64BitChunks > 1) {
Serial.print(F(" Data[1]=0x"));
- Serial.print(aDecodedRawDataArray[1], HEX);
+ Serial.print(aDecodedRawDataPGMArray[1], HEX);
}
Serial.print(F(" #="));
Serial.println(aNumberOfBits);
Serial.flush();
#endif
- uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
- auto tStartOfFrameMillis = millis();
- auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
+ unsigned long tStartOfFrameMillis = millis();
// Header
- mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
- space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
- uint8_t tOriginalFlags = aProtocolConstants->Flags;
+ mark(aHeaderMarkMicros);
+ space(aHeaderSpaceMicros);
for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
uint8_t tNumberOfBitsForOneSend;
+ // Manage stop bit
uint8_t tFlags;
if (i == (tNumberOf32Or64BitChunks - 1)) {
// End of data
- tNumberOfBitsForOneSend = tNumberOfBits;
- tFlags = tOriginalFlags;
+ tNumberOfBitsForOneSend = aNumberOfBits;
+ tFlags = aFlags;
} else {
// intermediate data
tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
- tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
+ tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
}
- sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
- aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
- aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
- aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend,
- tFlags);
- tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
+ IRRawDataType tDecodedRawData;
+#if (__INT_WIDTH__ < 32)
+ tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]); // pgm_read_dword reads 32 bit on AVR
+#else
+ tDecodedRawData = aDecodedRawDataPGMArray[i]; // assume non Harvard architecture here
+#endif
+ sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, tDecodedRawData,
+ tNumberOfBitsForOneSend, tFlags);
+ aNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
tNumberOfCommands--;
@@ -673,13 +878,47 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants
* 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 (aRepeatPeriodMillis > tFrameDurationMillis) {
+ delay(aRepeatPeriodMillis - tFrameDurationMillis);
}
}
}
}
+/**********************************************************************************************************************
+ * Stubs for send functions
+ **********************************************************************************************************************/
+
+/**
+ * Sends PulseDistance data from array
+ * 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. Stop bit is otherwise sent for all pulse distance protocols.
+ */
+void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
+ IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
+ int_fast8_t aNumberOfRepeats) {
+ sendPulseDistanceWidthFromArray(aFrequencyKHz, aDistanceWidthTimingInfo->HeaderMarkMicros,
+ aDistanceWidthTimingInfo->HeaderSpaceMicros, aDistanceWidthTimingInfo->OneMarkMicros,
+ aDistanceWidthTimingInfo->OneSpaceMicros, aDistanceWidthTimingInfo->ZeroMarkMicros,
+ aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis,
+ aNumberOfRepeats);
+}
+
+void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz,
+ DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRRawDataType *aDecodedRawDataArray,
+ uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) {
+
+ DistanceWidthTimingInfoStruct tTemporaryDistanceWidthTimingInfo;
+ memcpy_P(&tTemporaryDistanceWidthTimingInfo, aDistanceWidthTimingInfoPGM, sizeof(tTemporaryDistanceWidthTimingInfo));
+ sendPulseDistanceWidthFromArray(aFrequencyKHz, &tTemporaryDistanceWidthTimingInfo, aDecodedRawDataArray, aNumberOfBits, aFlags,
+ aRepeatPeriodMillis, aNumberOfRepeats);
+}
+
+/**********************************************************************************************************************
+ * Send functions with PulseDistanceWidthProtocolConstants parameter
+ **********************************************************************************************************************/
/**
* Sends PulseDistance frames and repeats
* @param aProtocolConstants The constants to use for sending this protocol.
@@ -700,7 +939,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
#endif
if (aNumberOfRepeats < 0) {
- if (aProtocolConstants->SpecialSendRepeatFunction != NULL) {
+ if (aProtocolConstants->SpecialSendRepeatFunction != nullptr) {
/*
* Send only a special repeat and return
*/
@@ -719,7 +958,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
- if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aProtocolConstants->SpecialSendRepeatFunction != NULL) {
+ if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aProtocolConstants->SpecialSendRepeatFunction != nullptr) {
// send special repeat, if specified and we are not in the first loop
aProtocolConstants->SpecialSendRepeatFunction();
} else {
@@ -732,6 +971,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
}
tNumberOfCommands--;
+
// skip last delay!
if (tNumberOfCommands > 0) {
auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis;
@@ -746,45 +986,72 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc
}
/**
- * Sends PulseDistance frames and repeats.
- * @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. Stop bit is otherwise sent for all pulse distance protocols.
+ * Sends PulseDistance data from array using PulseDistanceWidthProtocolConstants
+ * 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.
- * @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, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats,
- void (*aSpecialSendRepeatFunction)()) {
-
- if (aNumberOfRepeats < 0) {
- if (aSpecialSendRepeatFunction != NULL) {
- aSpecialSendRepeatFunction();
- return;
- } else {
- aNumberOfRepeats = 0; // send a plain frame as repeat
- }
- }
+void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
+ IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
+// Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
+// sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
+// aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
+// aNumberOfRepeats);
// Set IR carrier frequency
- enableIROut(aFrequencyKHz);
+ enableIROut(aProtocolConstants->FrequencyKHz);
+
+ uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
+
+#if defined(LOCAL_DEBUG)
+ // fist data
+ Serial.print(F("Data[0]=0x"));
+ Serial.print(aDecodedRawDataArray[0], HEX);
+ if (tNumberOf32Or64BitChunks > 1) {
+ Serial.print(F(" Data[1]=0x"));
+ Serial.print(aDecodedRawDataArray[1], HEX);
+ }
+ Serial.print(F(" #="));
+ Serial.println(aNumberOfBits);
+ Serial.flush();
+#endif
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
- unsigned long tStartOfFrameMillis = millis();
+ auto tStartOfFrameMillis = millis();
+ auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
- if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != NULL) {
- // send special repeat
- aSpecialSendRepeatFunction();
- } else {
- // Header and regular frame
- mark(aHeaderMarkMicros);
- space(aHeaderSpaceMicros);
- sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits,
- aFlags);
+ // Header
+ mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
+ space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
+ uint8_t tOriginalFlags = aProtocolConstants->Flags;
+
+ for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
+ uint8_t tNumberOfBitsForOneSend;
+
+ uint8_t tFlags;
+ if (i == (tNumberOf32Or64BitChunks - 1)) {
+ // End of data
+ tNumberOfBitsForOneSend = tNumberOfBits;
+ tFlags = tOriginalFlags;
+ } else {
+ // intermediate data
+ tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
+ tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
+ }
+
+ sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend,
+ tFlags);
+ tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
tNumberOfCommands--;
@@ -794,97 +1061,136 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader
* Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration.
*/
auto tFrameDurationMillis = millis() - tStartOfFrameMillis;
- if (aRepeatPeriodMillis > tFrameDurationMillis) {
- delay(aRepeatPeriodMillis - tFrameDurationMillis);
+ if (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) {
+ delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis);
}
}
}
}
-/**
- * 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) {
+void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
- sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
- aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
- aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags);
-}
+// Calling sendPulseDistanceWidthFromArray() costs 68 bytes program memory compared to the implementation below
+// sendPulseDistanceWidthFromArray(aProtocolConstants->FrequencyKHz, aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
+// aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros,
+// aDecodedRawDataArray, aNumberOfBits, aProtocolConstants->Flags, aProtocolConstants->RepeatPeriodMillis,
+// aNumberOfRepeats);
+ // Set IR carrier frequency
+ enableIROut(aProtocolConstants->FrequencyKHz);
-/**
- * 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. 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, uint8_t aFlags) {
+ uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1;
#if defined(LOCAL_DEBUG)
- Serial.print(aData, HEX);
- Serial.print('|');
+ // fist data
+ Serial.print(F("Data[0]=0x"));
+ Serial.print(aDecodedRawDataPGMArray[0], HEX);
+ if (tNumberOf32Or64BitChunks > 1) {
+ Serial.print(F(" Data[1]=0x"));
+ Serial.print(aDecodedRawDataPGMArray[1], HEX);
+ }
+ Serial.print(F(" #="));
Serial.println(aNumberOfBits);
Serial.flush();
#endif
- // For MSBFirst, send data from MSB to LSB until mask bit is shifted out
- IRRawDataType tMask = 1ULL << (aNumberOfBits - 1);
- for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
- if (((aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & tMask)) || (!(aFlags & PROTOCOL_IS_MSB_FIRST) && (aData & 1))) {
-#if defined(LOCAL_TRACE)
- Serial.print('1');
-#endif
- mark(aOneMarkMicros);
- space(aOneSpaceMicros);
- } else {
-#if defined(LOCAL_TRACE)
- Serial.print('0');
+ uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
+ while (tNumberOfCommands > 0) {
+ auto tStartOfFrameMillis = millis();
+ auto tNumberOfBits = aNumberOfBits; // refresh value for repeats
+
+ // Header
+ mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros);
+ space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros);
+ uint8_t tOriginalFlags = aProtocolConstants->Flags;
+
+ for (uint_fast8_t i = 0; i < tNumberOf32Or64BitChunks; ++i) {
+ uint8_t tNumberOfBitsForOneSend;
+
+ uint8_t tFlags;
+ if (i == (tNumberOf32Or64BitChunks - 1)) {
+ // End of data
+ tNumberOfBitsForOneSend = tNumberOfBits;
+ tFlags = tOriginalFlags;
+ } else {
+ // intermediate data
+ tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE;
+ tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data
+ }
+
+ IRRawDataType tDecodedRawData;
+#if (__INT_WIDTH__ < 32)
+ tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]); // pgm_read_dword reads 32 bit on AVR
+#else
+ tDecodedRawData = aDecodedRawDataPGMArray[i]; // assume non Harvard architecture here
#endif
- mark(aZeroMarkMicros);
- space(aZeroSpaceMicros);
+ sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
+ aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, tDecodedRawData, tNumberOfBitsForOneSend, tFlags);
+ tNumberOfBits -= BITS_IN_RAW_DATA_TYPE;
}
- if (aFlags & PROTOCOL_IS_MSB_FIRST) {
- tMask >>= 1;
- } else {
- aData >>= 1;
+
+ 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 (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) {
+ delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis);
+ }
}
}
- /*
- * Stop bit is sent for all pulse distance protocols i.e. aOneSpaceMicros != aZeroSpaceMicros.
- * Therefore it is not sent for Sony :-)
- * For sending from an array, no intermediate stop bit must be sent for all but last data chunk.
- */
- if ((!(aFlags & SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) {
- // Send stop bit here
-#if defined(LOCAL_TRACE)
- Serial.print('S');
-#endif
- mark(aOneMarkMicros); // Use aOneMarkMicros for stop bits. This seems to be correct for all protocols :-)
- }
-#if defined(LOCAL_TRACE)
- Serial.println();
-#endif
+}
+
+/**********************************************************************************************************************
+ * Stubs for send functions with PulseDistanceWidthProtocolConstants parameter
+ **********************************************************************************************************************/
+
+void IRsend::sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
+
+ PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
+ memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
+ sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
+ sendPulseDistanceWidthFromArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataArray, aNumberOfBits,
+ aNumberOfRepeats);
+}
+void IRsend::sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
+
+ PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
+ memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
+ sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
+ sendPulseDistanceWidthFromPGMArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataPGMArray, aNumberOfBits,
+ aNumberOfRepeats);
+}
+
+void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData,
+ uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) {
+ PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
+ memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
+ sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
+ sendPulseDistanceWidth(&tTemporaryPulseDistanceWidthProtocolConstants, aData, aNumberOfBits, aNumberOfRepeats);
}
/**
- * Sends Biphase data MSB first
- * Always send start bit, do not send the trailing space of the start bit
+ * Sends Biphase (Manchester) coded data MSB first
+ * This function concatenates two marks to one longer mark,
+ * thus avoiding the programmatically pause between the generation of two separate marks.
+ * Send an additional start bit if specified
* 0 -> mark+space
* 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.
+ * @param aSendStartBit if true sends an additional start bit with value 1 as MSB, if false no start bit is sent and data may start with 0 or 1.
*/
-void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) {
+void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits, bool aSendStartBit) {
IR_TRACE_PRINT(F("0x"));
IR_TRACE_PRINT(aData, HEX);
@@ -895,10 +1201,28 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas
// Data - Biphase code MSB first
// prepare for start with sending the start bit, which is 1
- uint32_t tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit
- uint_fast8_t tLastBitValue = 1; // Start bit is a 1
- bool tNextBitIsOne = 1; // Start bit is a 1
- for (uint_fast8_t i = aNumberOfBits + 1; i > 0; i--) {
+ uint32_t tMask;
+ uint_fast8_t tLastBitValue;
+ bool tNextBitIsOne;
+ uint8_t tBitsToSend; // total number of bits to send including start bit if specified
+
+ // Data - Biphase code MSB first
+ tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit
+ if (aSendStartBit) {
+ tBitsToSend = aNumberOfBits + 1; // +1 for additional start bit
+ // prepare for start with sending the start bit, which is 1
+ tNextBitIsOne = 1; // Start bit is a 1, value is copied to tCurrentBitIsOne
+ tLastBitValue = 0; // Force to send the mark if tNextBitIsOne is 0 (which it is not here). Does not increase code size :-).
+ } else {
+ // prepare to send only the data which may start with a 0 or 1 (e.g. after a defined pause or header when no additional start bit is needed)
+ tMask = 1UL >> 1; // mask is now set for the MSB of data
+ tBitsToSend = aNumberOfBits;
+ tNextBitIsOne = ((aData & tMask) != 0) ? 1 : 0; // Value is copied to tCurrentBitIsOne
+ tLastBitValue = 0; // Force to send the mark if tNextBitIsOne is 0
+ }
+
+ // now send all bits
+ for (uint_fast8_t i = tBitsToSend; i > 0; i--) {
bool tCurrentBitIsOne = tNextBitIsOne;
tMask >>= 1;
tNextBitIsOne = ((aData & tMask) != 0) || (i == 1); // true for last bit to avoid extension of mark
@@ -908,7 +1232,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas
#endif
space(aBiphaseTimeUnit);
if (tNextBitIsOne) {
- mark(aBiphaseTimeUnit);
+ mark(aBiphaseTimeUnit); // if next bit is 1 send a single mark
} else {
// if next bit is 0, extend the current mark in order to generate a continuous signal without short breaks
mark(2 * aBiphaseTimeUnit);
@@ -919,14 +1243,14 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas
#if defined(LOCAL_TRACE)
Serial.print('0');
#endif
- if (!tLastBitValue) {
- mark(aBiphaseTimeUnit);
+ if (tLastBitValue == 0) {
+ mark(aBiphaseTimeUnit); // if next bit is 1 send a single mark
}
space(aBiphaseTimeUnit);
tLastBitValue = 0;
}
}
- IR_TRACE_PRINTLN(F(""));
+ IR_TRACE_PRINTLN();
}
/**
@@ -947,10 +1271,8 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas
void IRsend::mark(uint16_t aMarkMicros) {
#if defined(SEND_PWM_BY_TIMER) || defined(USE_NO_SEND_PWM)
-# if !defined(NO_LED_FEEDBACK_CODE)
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(true);
- }
+# if defined(LED_SEND_FEEDBACK_CODE)
+ setFeedbackLED(true);
# endif
#endif
@@ -970,7 +1292,7 @@ void IRsend::mark(uint16_t aMarkMicros) {
# 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)
+# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM) || defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN) // USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN is old and deprecated
digitalWriteFast(sendPin, HIGH); // Set output to active high.
# else
digitalWriteFast(sendPin, LOW); // Set output to active low.
@@ -978,55 +1300,76 @@ void IRsend::mark(uint16_t aMarkMicros) {
customDelayMicroseconds(aMarkMicros);
IRLedOff();
-# if !defined(NO_LED_FEEDBACK_CODE)
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(false);
- }
+# if defined(LED_SEND_FEEDBACK_CODE)
+ setFeedbackLED(false);
return;
# endif
#else // defined(SEND_PWM_BY_TIMER)
- /*
- * Generate PWM by bit banging
- */
- unsigned long tStartMicros = micros();
- unsigned long tNextPeriodEnding = tStartMicros;
- unsigned long tMicros;
-# if !defined(NO_LED_FEEDBACK_CODE)
- bool FeedbackLedIsActive = false;
-# endif
+ unsigned long tMicrosOfEndOfNextPWMPause = micros();
+# if defined(LED_SEND_FEEDBACK_CODE)
+ unsigned long tStartMicros = tMicrosOfEndOfNextPWMPause + (136 / CLOCKS_PER_MICRO); // To compensate for call duration and activating of LED
+ bool tFeedbackLedIsActive = false;
+#else
+ unsigned long tStartMicros = tMicrosOfEndOfNextPWMPause + (112 / CLOCKS_PER_MICRO); // To compensate for call duration - 112 is an empirical value
+#endif
+
+ /***************************************************************************************************
+ * Generate the IR PWM with 30% duty cycle with a frequency of e.g. 38 kHz by software / bit banging
+ **************************************************************************************************/
do {
// digitalToggleFast(_IR_TIMING_TEST_PIN);
- /*
- * Output the PWM pulse
- */
+ /*****************************************
+ * Output the PWM pulse - IR LED is active
+ ****************************************/
noInterrupts(); // do not let interrupts extend the short on period
-# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
-# if defined(OUTPUT_OPEN_DRAIN)
- digitalWriteFast(sendPin, LOW); // set output with pin mode OUTPUT_OPEN_DRAIN to active low
+# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) || defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN)
+# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) || defined(OUTPUT_OPEN_DRAIN)
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, LOW); // set output to active low. Also applicable for pin with mode OUTPUT_OPEN_DRAIN :-)
+ } else {
+ digitalWrite(sendPin, LOW);
+ }
# else
pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain
# endif
# else
// 3.5 us from FeedbackLed on to pin setting. 5.7 us from call of mark() to pin setting incl. setting of feedback pin.
// 4.3 us from do{ to pin setting if sendPin is no constant
- digitalWriteFast(sendPin, HIGH);
+ // check must be here because of MegaTinyCore and its badArg() check
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, HIGH);
+ } else {
+ digitalWrite(sendPin, HIGH);
+ }
# endif
- delayMicroseconds (periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait.
-
/*
- * Output the PWM pause
+ * Timing for the on time of the e.g. 38 kHz signal.
+ * On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait.
*/
-# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN)
-# if defined(OUTPUT_OPEN_DRAIN)
- digitalWriteFast(sendPin, HIGH); // Set output with pin mode OUTPUT_OPEN_DRAIN to inactive high.
+ delayMicroseconds (periodOnTimeMicros);
+
+ /*******************************************
+ * Output the PWM pause - IR LED is inactive
+ ******************************************/
+# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) || defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN)
+# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) || defined(OUTPUT_OPEN_DRAIN)
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, HIGH); // Set output to inactive high. Also applicable for pin with mode OUTPUT_OPEN_DRAIN
+ } else {
+ digitalWrite(sendPin, HIGH);
+ }
# else
pinModeFast(sendPin, INPUT); // to mimic the open drain inactive state
# endif
# else
- digitalWriteFast(sendPin, LOW);
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, LOW);
+ } else {
+ digitalWrite(sendPin, LOW);
+ }
# endif
/*
* Enable interrupts at start of the longer off period. Required at least to keep micros correct.
@@ -1034,28 +1377,26 @@ void IRsend::mark(uint16_t aMarkMicros) {
*/
interrupts();
-# if !defined(NO_LED_FEEDBACK_CODE)
+# if defined(LED_SEND_FEEDBACK_CODE)
/*
* Delayed call of setFeedbackLED() to get better startup timing, especially required for consecutive marks
*/
- if (!FeedbackLedIsActive) {
- FeedbackLedIsActive = true;
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(true);
- }
+ if (!tFeedbackLedIsActive) {
+ tFeedbackLedIsActive = true; // do it only once
+ setFeedbackLED(true);
}
# endif
- /*
- * PWM pause timing
- * Measured delta between pause duration values are 13 us for a 16 MHz Uno (from 13 to 26), if interrupts are disabled below
- * Measured delta between pause duration values are 20 us for a 16 MHz Uno (from 7.8 to 28), if interrupts are not disabled below
- * Minimal pause duration is 5.2 us with NO_LED_FEEDBACK_CODE enabled
- * and 8.1 us with NO_LED_FEEDBACK_CODE disabled.
- */
- tNextPeriodEnding += periodTimeMicros;
+ /********************************************************************************************************************************
+ * Check for end of the PWM pause with micros() < tMicrosOfEndOfNextPWMPause.
+ * This generates the timing for the transmit frequency e.g. 38 kHz
+ * Measured delta between pause duration values are 8 us for a 16 MHz Uno (from 15 to 23), if interrupts are disabled below
+ * Minimal pause duration is 5.2 us
+ *******************************************************************************************************************************/
+ tMicrosOfEndOfNextPWMPause += periodTimeMicros;
#if defined(__AVR__) // micros() for STM sometimes give decreasing values if interrupts are disabled. See https://github.com/stm32duino/Arduino_Core_STM32/issues/1680
noInterrupts(); // disable interrupts (especially the 20 us receive interrupts) only at start of the PWM pause. Otherwise it may extend the pause too much.
#endif
+ unsigned long tMicros;
do {
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
@@ -1063,44 +1404,30 @@ void IRsend::mark(uint16_t aMarkMicros) {
/*
* For AVR @16MHz we have only 4 us resolution.
* The duration of the micros() call itself is 3 us.
- * It takes 0.9 us from signal going low here.
- * The rest of the loop takes 1.2 us with NO_LED_FEEDBACK_CODE enabled
- * and 3 us with NO_LED_FEEDBACK_CODE disabled.
+ * It takes 0.9 us from signal going low to here.
+ * The rest of the loop takes 1.2 us
*/
#if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
#endif
- /*
- * Exit the forever loop if aMarkMicros has reached
- */
+
+ /*************************************************
+ * Check for end of mark duration / PWM generation
+ ************************************************/
tMicros = micros();
uint16_t tDeltaMicros = tMicros - tStartMicros;
-#if defined(__AVR__)
// reset feedback led in the last pause before end
// tDeltaMicros += (160 / CLOCKS_PER_MICRO); // adding this once increases program size, so do it below !
-# if !defined(NO_LED_FEEDBACK_CODE)
- if (tDeltaMicros >= aMarkMicros - (30 + (112 / CLOCKS_PER_MICRO))) { // 30 to be constant. Using periodTimeMicros increases program size too much.
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(false);
- }
- }
-# endif
- // Just getting variables and check for end condition takes minimal 3.8 us
- if (tDeltaMicros >= aMarkMicros - (112 / CLOCKS_PER_MICRO)) { // To compensate for call duration - 112 is an empirical value
-#else
if (tDeltaMicros >= aMarkMicros) {
-# if !defined(NO_LED_FEEDBACK_CODE)
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(false);
- }
-# endif
+#if defined(LED_SEND_FEEDBACK_CODE)
+ setFeedbackLED(false);
#endif
#if defined(__AVR__)
interrupts();
#endif
return;
}
- } while (tMicros < tNextPeriodEnding);
+ } while (tMicros < tMicrosOfEndOfNextPWMPause); // = End of one PWM period
} while (true);
# endif
}
@@ -1117,33 +1444,40 @@ 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)
+# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM) || defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN) // USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN is old and deprecated
digitalWriteFast(sendPin, LOW); // Set output to inactive low.
# else
digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
# endif
#else
-# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
-# if defined(OUTPUT_OPEN_DRAIN)
- digitalWriteFast(sendPin, HIGH); // Set output to inactive high.
+# if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) || defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN)
+# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) || defined(OUTPUT_OPEN_DRAIN)
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, HIGH); // set output to inactive high.
+ } else {
+ digitalWrite(sendPin, HIGH);
+ }
# else
pinModeFast(sendPin, INPUT); // inactive state to mimic open drain
# endif
# else
- digitalWriteFast(sendPin, LOW);
+ if (__builtin_constant_p(sendPin)) {
+ digitalWriteFast(sendPin, LOW); // set output to active low.
+ } else {
+ digitalWrite(sendPin, LOW);
+ }
# endif
#endif
-#if !defined(NO_LED_FEEDBACK_CODE)
- if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) {
- setFeedbackLED(false);
- }
+#if defined(LED_SEND_FEEDBACK_CODE)
+ setFeedbackLED(false);
#endif
}
/**
* Sends an IR space for the specified number of microseconds.
* A space is "no output", so just wait.
+ * Executing program between end of mark and start of next mark uses around 15 to 20 us @ 16 MHz. This time is adds to the space delay here.
*/
void IRsend::space(uint16_t aSpaceMicros) {
customDelayMicroseconds(aSpaceMicros);
@@ -1183,7 +1517,7 @@ void IRsend::customDelayMicroseconds(unsigned long aMicroseconds) {
* Enables IR output. The kHz value controls the modulation frequency in kilohertz.
* IF PWM should be generated by a timer, it uses the platform specific timerConfigForSend() function,
* otherwise it computes the delays used by the mark() function.
- * If IR_SEND_PIN is defined, maximum PWM frequency for an AVR @16 MHz is 170 kHz (180 kHz if NO_LED_FEEDBACK_CODE is defined)
+ * If IR_SEND_PIN is defined, maximum PWM frequency for an AVR @16 MHz is 170 kHz (180 kHz if NO_LED_SEND_FEEDBACK_CODE is defined)
*/
void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER)
@@ -1216,7 +1550,11 @@ void IRsend::enableIROut(uint_fast8_t aFrequencyKHz) {
# if defined(IR_SEND_PIN)
pinModeFast(IR_SEND_PIN, OUTPUT);
# else
- pinModeFast(sendPin, OUTPUT);
+ if (__builtin_constant_p(sendPin)) {
+ pinModeFast(sendPin, OUTPUT);
+ } else {
+ pinMode(sendPin, OUTPUT);
+ }
# endif
# endif
#endif // defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN)
diff --git a/src/IRVersion.h b/src/IRVersion.h
index 668bb9a14..24890fc3f 100644
--- a/src/IRVersion.h
+++ b/src/IRVersion.h
@@ -6,7 +6,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2015-2024 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
+ * Copyright (c) 2015-2025 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -36,9 +36,9 @@
#ifndef _IR_VERSION_HPP
#define _IR_VERSION_HPP
-#define VERSION_IRREMOTE "4.4.0"
+#define VERSION_IRREMOTE "4.5.0"
#define VERSION_IRREMOTE_MAJOR 4
-#define VERSION_IRREMOTE_MINOR 4
+#define VERSION_IRREMOTE_MINOR 5
#define VERSION_IRREMOTE_PATCH 0
/*
diff --git a/src/IRremote.h b/src/IRremote.h
index 3af3f5829..73cae0385 100644
--- a/src/IRremote.h
+++ b/src/IRremote.h
@@ -9,14 +9,13 @@
#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 It seems, that you are using an 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 Upgrade instructions can be found here: "https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version"
+#warning Please use one of the new code examples from the library, available at "File > Examples > Examples from Custom Libraries / IRremote".
#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
+#warning The examples are documented here: "https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library"
+#warning Or just downgrade your library to version 2.6.0.
/**********************************************************************************************************************
* The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials
@@ -31,18 +30,19 @@ bool IRrecv::decode(decode_results *aResults) {
if (!sMessageWasSent) {
Serial.println(F("**************************************************************************************************"));
Serial.println(F("Thank you for using the IRremote library!"));
- Serial.println(F("It seems, that you are using a old version 2.0 code / example."));
+ Serial.println(F("It seems, that you are using an old version 2.0 code / example."));
Serial.println(F("This version is no longer supported!"));
+ Serial.println();
+ Serial.println(F("Upgrade instructions can be found here:"));
+ Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version"));
+ Serial.println();
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();
Serial.println(F("The examples are documented here:"));
- Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library"));
- Serial.println(F("A guide how to convert your 2.0 program is here:"));
- Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version"));
+ Serial.println(F(" https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library"));
+ Serial.println();
+ Serial.println(F("Or just downgrade your library to version 2.6.0."));
Serial.println();
Serial.println(F("Thanks"));
Serial.println(F("**************************************************************************************************"));
diff --git a/src/IRremote.hpp b/src/IRremote.hpp
index 657f06878..b84963e6f 100644
--- a/src/IRremote.hpp
+++ b/src/IRremote.hpp
@@ -13,7 +13,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2015-2023 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
+ * Copyright (c) 2015-2025 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -46,16 +46,21 @@
*
* - RAW_BUFFER_LENGTH Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits.
* - IR_SEND_PIN If specified (as constant), reduces program size and improves send timing for AVR.
+ * - USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN Reverts the polarity at the send pin.
+ * - 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!
* - SEND_PWM_BY_TIMER Disable carrier PWM generation in software and use (restricted) hardware PWM.
* - USE_NO_SEND_PWM Use no carrier PWM, just simulate an **active low** receiver signal. Overrides SEND_PWM_BY_TIMER definition.
- * - USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin!
+ * - USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM Simulate an **active high** receiver signal instead of an active low signal.
* - EXCLUDE_EXOTIC_PROTOCOLS If activated, BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF are excluded in decode() and in sending with IrSender.write().
* - EXCLUDE_UNIVERSAL_PROTOCOLS If activated, the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) are excluded in decode().
* - DECODE_* Selection of individual protocols to be decoded. See below.
+ * - USE_THRESHOLD_DECODER May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses.
* - MARK_EXCESS_MICROS Value is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules.
* - RECORD_GAP_MICROS Minimum gap between IR transmissions, to detect the end of a protocol.
* - FEEDBACK_LED_IS_ACTIVE_LOW Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low.
* - NO_LED_FEEDBACK_CODE This completely disables the LED feedback code for send and receive.
+ * - NO_LED_RECEIVE_FEEDBACK_CODE This disables the LED feedback code for receive.
+ * - NO_LED_SEND_FEEDBACK_CODE This disables the LED feedback code for send.
* - IR_INPUT_IS_ACTIVE_HIGH Enable it if you use a RF receiver, which has an active HIGH output signal.
* - IR_SEND_DUTY_CYCLE_PERCENT Duty cycle of IR send signal.
* - MICROS_PER_TICK Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 us at 38 kHz.
@@ -70,60 +75,7 @@
// activate it for all cores that does not use the -flto flag, if you get false error messages regarding begin() during compilation.
//#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN
-/*
- * If activated, BANG_OLUFSEN, BOSEWAVE, MAGIQUEST, WHYNTER, FAST and LEGO_PF are excluded in decoding and in sending with IrSender.write
- */
-//#define EXCLUDE_EXOTIC_PROTOCOLS
-/****************************************************
- * PROTOCOLS
- ****************************************************/
-/*
- * Supported IR protocols
- * Each protocol you include costs memory and, during decode, costs time
- * Copy the lines with the protocols you need in your program before the #include line
- * See also SimpleReceiver example
- */
-
-#if !defined(NO_DECODER) // for sending raw only
-# if (!(defined(DECODE_DENON) || defined(DECODE_JVC) || defined(DECODE_KASEIKYO) \
-|| defined(DECODE_PANASONIC) || defined(DECODE_LG) || defined(DECODE_NEC) || defined(DECODE_ONKYO) || defined(DECODE_SAMSUNG) \
-|| defined(DECODE_SONY) || defined(DECODE_RC5) || defined(DECODE_RC6) \
-|| defined(DECODE_DISTANCE_WIDTH) || defined(DECODE_HASH) || defined(DECODE_BOSEWAVE) \
-|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_FAST) || defined(DECODE_WHYNTER)))
-/*
- * If no protocol is explicitly enabled, we enable all protocols
- */
-#define DECODE_DENON // Includes Sharp
-#define DECODE_JVC
-#define DECODE_KASEIKYO
-#define DECODE_PANASONIC // alias for DECODE_KASEIKYO
-#define DECODE_LG
-#define DECODE_NEC // Includes Apple and Onkyo
-#define DECODE_SAMSUNG
-#define DECODE_SONY
-#define DECODE_RC5
-#define DECODE_RC6
-
-# if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory
-#define DECODE_BOSEWAVE
-#define DECODE_LEGO_PF
-#define DECODE_MAGIQUEST
-#define DECODE_WHYNTER
-#define DECODE_FAST
-# endif
-
-# if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS)
-#define DECODE_DISTANCE_WIDTH // universal decoder for pulse distance width protocols - requires up to 750 bytes additional program memory
-#define DECODE_HASH // special decoder for all protocols - requires up to 250 bytes additional program memory
-# endif
-# endif
-#endif // !defined(NO_DECODER)
-
-//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It prevents decoding of SONY!
-
-#if defined(DECODE_NEC) && !(~(~DECODE_NEC + 0) == 0 && ~(~DECODE_NEC + 1) == 1)
-#warning "The macros DECODE_XXX no longer require a value. Decoding is now switched by defining / non defining the macro."
-#endif
+#include "IRProtocol.h"
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core.
@@ -132,22 +84,26 @@
****************************************************/
/**
* 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
+ * to compensate for the signal forming of different IR receiver modules.
+ * 20 is taken as default if not otherwise specified / defined.
* For Vishay TSOP*, marks tend to be too long and spaces tend to be too short.
- * If you set MARK_EXCESS_MICROS to approx. 50us then the TSOP4838 works best.
- * At 100us it also worked, but not as well.
- * Set MARK_EXCESS to 100us and the VS1838 doesn't work at all.
- *
- * The right value is critical for IR codes using short pulses like Denon / Sharp / Lego
+ * If you set MARK_EXCESS_MICROS to approx. 40 to 50 us then the TSOP4838 works best.
+ * At 100 us it also worked, but not as well.
+ * Set MARK_EXCESS to 100 us and the VS1838 doesn't work at all.
*
* Observed values:
- * Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level.
- * VS1838 Mark Excess -50 at low intensity to +50 us at high intensity
+ * Delta of each signal type is around 50 up to 100 us and at low signals up to 200 us.
+ * TSOP is better, especially at low IR signal level.
+ * VS1838 Mark Excess -50 us at low intensity to +50 us at high intensity
* TSOP31238 Mark Excess 0 to +50
*/
#if !defined(MARK_EXCESS_MICROS)
-// To change this value, you simply can add a line #define "MARK_EXCESS_MICROS " in your ino file before the line "#include "
-#define MARK_EXCESS_MICROS 20
+# if defined(USE_THRESHOLD_DECODER)
+#define MARK_EXCESS_MICROS 0 // MARK_EXCESS_MICROS is not very relevant here, so we set it to 0 to save up to 164 bytes programming space
+# else
+// To override this value, you simply can add a line #define "MARK_EXCESS_MICROS " in your ino file before the line "#include "
+#define MARK_EXCESS_MICROS 20 // a value != 0 requires up to 100 bytes program space
+# endif
#endif
/**
@@ -243,6 +199,7 @@
#define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code
#endif
+
/**
* microseconds per clock interrupt tick
*/
@@ -254,17 +211,33 @@
#define MICROS_IN_ONE_SECOND 1000000L
#define MICROS_IN_ONE_MILLI 1000L
+#if defined(NO_LED_FEEDBACK_CODE)
+// convert to receive and send macros
+# if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
+#define NO_LED_RECEIVE_FEEDBACK_CODE
+# endif
+# if !defined(NO_LED_SEND_FEEDBACK_CODE)
+#define NO_LED_SEND_FEEDBACK_CODE
+# endif
+#endif
+#if defined(NO_LED_RECEIVE_FEEDBACK_CODE) && defined(NO_LED_SEND_FEEDBACK_CODE) && !defined(NO_LED_FEEDBACK_CODE)
+#define NO_LED_FEEDBACK_CODE
+#endif
+
#include "IRremoteInt.h"
/*
* We always use digitalWriteFast() and digitalReadFast() functions to have a consistent mapping for pins.
* For most non AVR cpu's, it is just a mapping to digitalWrite() and digitalRead() functions.
*/
+#if !defined(MEGATINYCORE) // megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast().
#include "digitalWriteFast.h"
+#endif
#if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
#include "private/IRTimer.hpp" // defines IR_SEND_PIN for AVR and SEND_PWM_BY_TIMER
-# if !defined(NO_LED_FEEDBACK_CODE)
+# if !defined(NO_LED_FEEDBACK_CODE) && !(defined(DISABLE_CODE_FOR_RECEIVER) && defined(NO_LED_SEND_FEEDBACK_CODE))
+// Led feedback code enabled here
# if !defined(LED_BUILTIN)
/*
* print a warning
@@ -306,7 +279,7 @@ void disableLEDFeedback() {}; // dummy function for examples
#include "ir_Others.hpp"
#include "ir_Pronto.hpp" // pronto is an universal decoder and encoder
# if defined(DECODE_DISTANCE_WIDTH) // universal decoder for pulse distance width protocols - requires up to 750 bytes additional program memory
-#include
+#include "ir_DistanceWidthProtocol.hpp"
# endif
#endif // #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE)
diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h
index fc204e0c1..1c52c6afa 100644
--- a/src/IRremoteInt.h
+++ b/src/IRremoteInt.h
@@ -9,7 +9,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2015-2023 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
+ * Copyright (c) 2015-2025 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -56,13 +56,6 @@
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
//#define TRACE // Activate this for more debug output.
-/**
- * For better readability of code
- */
-#define DISABLE_LED_FEEDBACK false
-#define ENABLE_LED_FEEDBACK true
-#define USE_DEFAULT_FEEDBACK_LED_PIN 0
-
/**
* The RAW_BUFFER_LENGTH determines the length of the byte buffer where the received IR timing data is stored before decoding.
* 100 is sufficient for standard protocols up to 48 bits, with 1 bit consisting of one mark and space plus 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit.
@@ -73,7 +66,10 @@
* Air conditioners often send a longer protocol data stream up to 750 bits.
*/
#if !defined(RAW_BUFFER_LENGTH)
-# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
+# if (defined(RAMEND) && RAMEND <= 0x2FF) || (defined(RAMSIZE) && RAMSIZE < 0x2FF)
+// for RAMsize <= 512 bytes
+#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
+# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
// for RAMsize <= 2k
#define RAW_BUFFER_LENGTH 200 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
# else
@@ -99,7 +95,7 @@ typedef unsigned int IRRawlenType;
* we can choose to use a 8 bit buffer even for frame gaps up to 200000 us.
* This enables the use of 8 bit buffer even for more some protocols like B&O or LG air conditioner etc.
*/
-#if RECORD_GAP_TICKS <= 400 // Corresponds to RECORD_GAP_MICROS of 200000. A value of 255 is foolproof, but we assume, that the frame gap is
+#if RECORD_GAP_TICKS <= 400 // Corresponds to RECORD_GAP_MICROS of 200000. A value of 255 is foolproof, but we assume, that the frame gap is way greater than the biggest mark or space duration.
typedef uint8_t IRRawbufType; // all timings up to the gap fit into 8 bit.
#else
typedef uint16_t IRRawbufType; // The gap does not fit into 8 bit ticks value. This must not be a reason to use 16 bit for buffer, but it is at least save.
@@ -113,9 +109,9 @@ typedef uint64_t IRRawDataType;
#define BITS_IN_RAW_DATA_TYPE 64
#endif
-/****************************************************
+/**********************************************************
* Declarations for the receiver Interrupt Service Routine
- ****************************************************/
+ **********************************************************/
// ISR State-Machine : Receiver States
#define IR_REC_STATE_IDLE 0 // Counting the gap time and waiting for the start bit to arrive
#define IR_REC_STATE_MARK 1 // A mark was received and we are counting the duration of it.
@@ -123,8 +119,8 @@ typedef uint64_t IRRawDataType;
#define IR_REC_STATE_STOP 3 // Stopped until set to IR_REC_STATE_IDLE which can only be done by resume()
/**
- * This struct contains the data and control used for receiver static functions and the ISR (interrupt service routine)
- * Only StateForISR needs to be volatile. All the other fields are not written by ISR after data available and before start/resume.
+ * This struct contains the data and control used for receiver functions and the ISR (interrupt service routine)
+ * Only StateForISR needs to be volatile. All the other fields are not written by ISR after available() == true and before start() / resume().
*/
struct irparams_struct {
// The fields are ordered to reduce memory overflow caused by struct-padding
@@ -144,7 +140,36 @@ struct irparams_struct {
IRRawbufType rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space. With 8 bit we can only store up to 12.7 ms. First entry is empty to be backwards compatible.
};
-#include "IRProtocol.h"
+extern unsigned long sMicrosAtLastStopTimer; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer()
+
+#define DECODED_RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_RAW_DATA_TYPE)) + 1) // The -2 is for initial gap + stop bit mark, 128 mark + spaces for 64 bit.
+/**
+ * Data structure for the user application, available as decodedIRData.
+ * Filled by decoders and read by print functions or user application.
+ */
+struct IRData {
+ decode_type_t protocol; ///< UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
+ uint16_t address; ///< Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << 8) | tSpaceTicksLong
+ uint16_t command; ///< Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort
+ uint16_t extra; ///< Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMarkTicks << 8) | HeaderSpaceTicks.
+ IRRawDataType decodedRawData; ///< Up to 32/64 bit decoded raw data, to be used for sendRaw functions.
+#if defined(DECODE_DISTANCE_WIDTH)
+ // This replaces the address, command, extra and decodedRawData in case of protocol == PULSE_DISTANCE or -rather seldom- protocol == PULSE_WIDTH.
+ DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes
+ IRRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; ///< 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions.
+#endif
+ uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
+ uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above
+
+ /*
+ * These 2 variables allow to call resume() directly after decode.
+ * After resume(), irparams.initialGapTicks and irparams.rawlen are
+ * the first variables, which are overwritten by the next received frame.
+ * since 4.3.0.
+ */
+ IRRawlenType rawlen; ///< Counter of entries in rawbuf of last received frame.
+ uint16_t initialGapTicks; ///< Contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
+};
/*
* Debug directives
@@ -189,42 +214,48 @@ struct decode_results {
bool isRepeat; // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected
// 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
+ uint16_t *rawbuf; // deprecated, moved to irparams.rawbuf ///< Raw intervals in 50uS ticks
+ uint_fast8_t rawlen; // deprecated, moved to irparams.rawlen ///< Number of records in rawbuf
bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long
};
/**
* Main class for receiving IR signals
*/
+#define USE_DEFAULT_FEEDBACK_LED_PIN 0 // we need it here
class IRrecv {
public:
IRrecv();
+#if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES)
IRrecv(uint_fast8_t aReceivePin);
IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin);
+#else
+ IRrecv(
+ uint_fast8_t aReceivePin)
+ __attribute__ ((deprecated ("Please use the default IRrecv instance \"IrReceiver\" and IrReceiver.begin(), and not your own IRrecv instance.")));
+ IRrecv(uint_fast8_t aReceivePin,
+ uint_fast8_t aFeedbackLEDPin)
+ __attribute__ ((deprecated ("Please use the default IRrecv instance \"IrReceiver\" and IrReceiver.begin(), and not your own IRrecv instance..")));
+#endif
void setReceivePin(uint_fast8_t aReceivePinNumber);
#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
void registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void));
#endif
+ void ReceiveInterruptHandler();
/*
* 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();
void restartTimer(uint32_t aMicrosecondsToAddToGapCounter);
- void startWithTicksToAdd(uint16_t aTicksToAddToGapCounter);
void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter);
void restartAfterSend();
- void addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter);
- void addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter);
-
bool available();
IRData* read(); // returns decoded data
// write is a method of class IRsend below
@@ -246,6 +277,7 @@ class IRrecv {
* Useful info and print functions
*/
void printIRResultMinimal(Print *aSerial);
+ void printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks);
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void printIRResultAsCVariables(Print *aSerial);
uint8_t getMaximumMarkTicksFromRawData();
@@ -256,7 +288,9 @@ class IRrecv {
/*
* Next 4 functions are also available as non member functions
*/
- bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap = true, bool aCheckForRecordGapsMicros = true);
+ bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros)
+ __attribute__ ((deprecated ("Remove second parameter, it is not supported any more.")));
+ bool printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros = true);
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo);
void printIRSendUsage(Print *aSerial);
#if defined(__AVR__)
@@ -266,6 +300,7 @@ class IRrecv {
#endif
static void printActiveIRProtocols(Print *aSerial);
+ void printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true, bool aDoCompensate = true);
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
void compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t frequency = 38000U);
@@ -278,18 +313,32 @@ class IRrecv {
/*
* The main decoding functions used by the individual decoders
*/
- bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
+#if defined(USE_STRICT_DECODER)
+ bool
+#else
+ void
+#endif
+ decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
IRRawlenType aStartOffset = 3);
- bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ void decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset = 3);
+
+ void decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMicros,
+ bool aIsPulseWidthProtocol, bool aMSBfirst);
+
+ void decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset,
+ uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst);
+
+ void decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst);
- bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ void decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst)
__attribute__ ((deprecated ("Please use decodePulseDistanceWidthData() with 6 parameters.")));
- bool decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
- uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst);
+ bool decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
+ uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst);
bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint_fast8_t aStartClockCount,
uint_fast8_t aValueOfSpaceToMarkTransition, uint16_t aBiphaseTimeUnit);
@@ -352,25 +401,39 @@ class IRrecv {
void initDecodedIRData();
uint_fast8_t compare(uint16_t oldval, uint16_t newval);
bool checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants);
+ bool checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM);
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks);
bool checkForRecordGapsMicros(Print *aSerial);
+ irparams_struct irparams;
IRData decodedIRData; // Decoded IR data for the application
- // Last decoded IR data for repeat detection and parity for Denon autorepeat
+ // Last decoded IR data for repeat detection and to fill in JVC, LG, NEC repeat values. Parity for Denon autorepeat
decode_type_t lastDecodedProtocol;
- uint32_t lastDecodedAddress;
- uint32_t lastDecodedCommand;
+ uint16_t lastDecodedAddress;
+ uint16_t lastDecodedCommand;
+#if defined(DECODE_DISTANCE_WIDTH)
+ IRRawDataType lastDecodedRawData;
+#endif
uint8_t repeatCount; // Used e.g. for Denon decode for autorepeat decoding.
};
-extern uint_fast8_t sBiphaseDecodeRawbuffOffset; //
+void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap)
+ __attribute__ ((deprecated ("Remove last parameter, it is not supported any more.")));
+void printIRResultShort(Print *aSerial, IRData *aIRDataPtr)
+ __attribute__ ((deprecated ("Use member function or printIRDataShort() instead.")));
+;
+// A static function to be able to print send or copied received data.
+void printIRDataShort(Print *aSerial, IRData *aIRDataPtr);
+
+extern uint_fast8_t sBiphaseDecodeRawbuffOffset;
/*
* Mark & Space matching functions
*/
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
+bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks);
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
@@ -388,13 +451,12 @@ void printActiveIRProtocols(Print *aSerial);
/****************************************************
* Feedback LED related functions
****************************************************/
-#define DO_NOT_ENABLE_LED_FEEDBACK 0x00
-#define LED_FEEDBACK_DISABLED_COMPLETELY 0x00
-#define LED_FEEDBACK_ENABLED_FOR_RECEIVE 0x01
-#define LED_FEEDBACK_ENABLED_FOR_SEND 0x02
-void setFeedbackLED(bool aSwitchLedOn);
-void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback); // if aFeedbackLEDPin == 0, then take board BLINKLED_ON() and BLINKLED_OFF() functions
+#define DISABLE_LED_FEEDBACK false
+#define ENABLE_LED_FEEDBACK true
+//#define USE_DEFAULT_FEEDBACK_LED_PIN 0 // repeated definition for info
void setLEDFeedback(bool aEnableLEDFeedback); // Direct replacement for blink13()
+void setLEDFeedbackPin(uint8_t aFeedbackLEDPin);
+void setFeedbackLED(bool aSwitchLedOn);
void enableLEDFeedback();
constexpr auto enableLEDFeedbackForReceive = enableLEDFeedback; // alias for enableLEDFeedback
void disableLEDFeedback();
@@ -415,8 +477,8 @@ void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please us
#define TICKS(us) ((us)/MICROS_PER_TICK) // (us)/50
#if MICROS_PER_TICK == 50 && TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT == 25 // Defaults
-#define TICKS_LOW(us) ((us)/67 ) // 67 = MICROS_PER_TICK / ((100-25)/100) = (MICROS_PER_TICK * 100) / (100-25)
-#define TICKS_HIGH(us) (((us)/40) + 1) // 40 = MICROS_PER_TICK / ((100+25)/100) = (MICROS_PER_TICK * 100) / (100+25)
+#define TICKS_LOW(us) ((us)/67 ) // =(us * 0.75 /MICROS_PER_TICK), 67 = MICROS_PER_TICK / ((100-25)/100) = (MICROS_PER_TICK * 100) / (100-25)
+#define TICKS_HIGH(us) (((us)/40) + 1) // =(us * 1,25 /MICROS_PER_TICK), 40 = MICROS_PER_TICK / ((100+25)/100) = (MICROS_PER_TICK * 100) / (100+25)
#else
/** Lower tolerance for comparison of measured data */
//#define LTOL (1.0 - (TOLERANCE/100.))
@@ -461,25 +523,17 @@ class IRsend {
#if defined(IR_SEND_PIN)
void begin();
// 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() and enableLEDFeedback() or disableLEDFeedback() since version 4.3.")));
-# endif
+ void begin(uint_fast8_t aFeedbackLEDPin);
#else
IRsend(uint_fast8_t aSendPin);
void begin(uint_fast8_t aSendPin);
void setSendPin(uint_fast8_t aSendPin); // required if we use IRsend() as constructor
- // Since 4.0 guarded and without default parameter
- void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin); // aFeedbackLEDPin can be USE_DEFAULT_FEEDBACK_LED_PIN
#endif
+ void begin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin); // aFeedbackLEDPin is by default USE_DEFAULT_FEEDBACK_LED_PIN
+ void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)
+# if !defined (DOXYGEN)
+ __attribute__ ((deprecated ("Use begin(aSendPin, aFeedbackLEDPin) instead.")));
+# endif
size_t write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats = NO_REPEATS);
size_t write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats = NO_REPEATS);
@@ -489,32 +543,53 @@ class IRsend {
void enableHighFrequencyIROut(uint_fast16_t aFrequencyKHz); // Used for Bang&Olufsen
#endif
+ /*
+ * Array functions
+ */
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, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros,
+ uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
+ int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM,
+ IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
+
void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo,
IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis,
int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz,
+ DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRRawDataType *aDecodedRawDataArray,
+ uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
+ void sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData,
+ uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats);
void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData,
uint_fast8_t aNumberOfBits);
+ void sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData,
+ uint_fast8_t aNumberOfBits);
void 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, void (*aSpecialSendRepeatFunction)() = NULL);
+ int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = nullptr);
void 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)() = NULL)
+ int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = nullptr)
__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 sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);
+ void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits, bool aSendStartBit = true);
void mark(uint16_t aMarkMicros);
static void space(uint16_t aSpaceMicros);
@@ -522,11 +597,19 @@ class IRsend {
// 8 Bit array
void sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
- void sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
+ void sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
+ void sendRaw(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats);
+ void sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats);
// 16 Bit array
void sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
- void sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
+ void sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
+ void sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats);
+ void sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz,
+ uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats);
/*
* New send functions
@@ -539,11 +622,9 @@ class IRsend {
void sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack = false,
bool aUseDatalinkTiming = false);
void sendBoseWave(uint8_t aCommand, int_fast8_t aNumberOfRepeats = NO_REPEATS);
- void sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aSendSharp = false);
+ void sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aSendSharpFrameMarker = 0);
void sendDenonRaw(uint16_t aRawData, int_fast8_t aNumberOfRepeats = NO_REPEATS)
-#if !defined (DOXYGEN)
__attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
-#endif
void sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats);
void sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats);
@@ -570,7 +651,11 @@ class IRsend {
void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first
void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
+ void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats,
+ bool aEnableAutomaticToggle = true);
void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
+ void sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aCustomer,
+ 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);
@@ -578,6 +663,7 @@ class IRsend {
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
+ void sendSharp2(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); // redirected to sendDenon
void sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits = 12); // SIRCS_12_PROTOCOL
void sendLegoPowerFunctions(uint8_t aChannel, uint8_t tCommand, uint8_t aMode, bool aDoSend5Times = true);
@@ -628,7 +714,7 @@ class IRsend {
void sendRC6(uint32_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC6Raw().")));
void sendRC6Raw(uint64_t data, uint8_t nbits);
void sendRC6(uint64_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC6Raw().")));
- ;
+
void sendSharpRaw(unsigned long data, int nbits);
void sendSharp(uint16_t address, uint16_t command);
void sendSAMSUNG(unsigned long data, int nbits);
@@ -638,8 +724,10 @@ class IRsend {
void sendSony(unsigned long data,
int nbits)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).")));
- ;
- void sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend);
+
+ void sendWhynter(uint32_t aData, int_fast8_t aNumberOfRepeats);
+ void sendVelux(uint8_t aCommand, uint8_t aMotorNumber, uint8_t aMotorSet, uint16_t aSecurityCode, int_fast8_t aNumberOfRepeats);
+ void sendVelux(uint32_t aData, int_fast8_t aNumberOfRepeats);
#if !defined(IR_SEND_PIN)
uint8_t sendPin;
diff --git a/src/TinyIR.h b/src/TinyIR.h
index 4f89fa2c5..ea1ce7bf5 100644
--- a/src/TinyIR.h
+++ b/src/TinyIR.h
@@ -2,7 +2,7 @@
* TinyIR.h
*
*
- * Copyright (C) 2021-2023 Armin Joachimsmeyer
+ * Copyright (C) 2021-2025 Armin Joachimsmeyer
* armin.joachimsmeyer@gmail.com
*
* This file is part of IRMP https://github.com/IRMP-org/IRMP.
@@ -34,9 +34,9 @@
* @{
*/
-#define VERSION_TINYIR "2.1.0"
+#define VERSION_TINYIR "2.2.0"
#define VERSION_TINYIR_MAJOR 2
-#define VERSION_TINYIR_MINOR 1
+#define VERSION_TINYIR_MINOR 2
#define VERSION_TINYIR_PATCH 0
// The change log is at the bottom of the file
@@ -53,14 +53,14 @@
#define NEC_UNIT 560
-#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000
-#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500
+#define NEC_HEADER_MARK (16 * NEC_UNIT) // 8860
+#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4480
#define NEC_BIT_MARK NEC_UNIT
-#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690
+#define NEC_ONE_SPACE (3 * NEC_UNIT) // 1680
#define NEC_ZERO_SPACE NEC_UNIT
-#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250
+#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2240
#define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
#define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
@@ -122,10 +122,12 @@
#define TINY_RECEIVER_HEADER_MARK FAST_HEADER_MARK
#define TINY_RECEIVER_HEADER_SPACE FAST_HEADER_SPACE
+#define TINY_RECEIVER_MARK_TIMEOUT (2 * FAST_HEADER_MARK)
#define TINY_RECEIVER_BIT_MARK FAST_BIT_MARK
#define TINY_RECEIVER_ONE_SPACE FAST_ONE_SPACE
#define TINY_RECEIVER_ZERO_SPACE FAST_ZERO_SPACE
+#define TINY_RECEIVER_ONE_THRESHOLD (2 * FAST_UNIT) // 1052
#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE FAST_MAXIMUM_REPEAT_DISTANCE // for repeat detection
@@ -151,11 +153,13 @@
#define TINY_RECEIVER_UNIT NEC_UNIT
#define TINY_RECEIVER_HEADER_MARK NEC_HEADER_MARK
+#define TINY_RECEIVER_MARK_TIMEOUT (2 * NEC_HEADER_MARK)
#define TINY_RECEIVER_HEADER_SPACE NEC_HEADER_SPACE
#define TINY_RECEIVER_BIT_MARK NEC_BIT_MARK
#define TINY_RECEIVER_ONE_SPACE NEC_ONE_SPACE
#define TINY_RECEIVER_ZERO_SPACE NEC_ZERO_SPACE
+#define TINY_RECEIVER_ONE_THRESHOLD (2 * NEC_UNIT) // 1120
#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE
#endif
@@ -218,11 +222,11 @@ struct TinyIRReceiverStruct {
/*
* Definitions for member TinyIRReceiverCallbackDataStruct.Flags
- * From IRremoteInt.h
+ * This is a copy of flags from IRremoteInt.h
*/
#define IRDATA_FLAGS_EMPTY 0x00
#define IRDATA_FLAGS_IS_REPEAT 0x01
-#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used here, overwritten with _IRDATA_FLAGS_IS_SHORT_REPEAT
+#define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used for TinyIR
#define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check
/**
@@ -243,7 +247,7 @@ struct TinyIRReceiverCallbackDataStruct {
uint8_t Command;
#endif
uint8_t Flags; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED
- bool justWritten; ///< Is set true if new data is available. Used by the main loop, to avoid multiple evaluations of the same IR frame.
+ bool justWritten; ///< Is set true if new data is available. Used by the main loop / TinyReceiverDecode(), to avoid multiple evaluations of the same IR frame.
};
extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
@@ -252,6 +256,7 @@ bool initPCIInterruptForTinyReceiver();
bool enablePCIInterruptForTinyReceiver();
void disablePCIInterruptForTinyReceiver();
bool isTinyReceiverIdle();
+bool TinyReceiverDecode();
void printTinyReceiverResultMinimal(Print *aSerial);
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0);
@@ -262,7 +267,23 @@ void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
+#if defined(NO_LED_FEEDBACK_CODE)
+# if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
+#define NO_LED_RECEIVE_FEEDBACK_CODE
+# endif
+# if !defined(NO_LED_SEND_FEEDBACK_CODE)
+#define NO_LED_SEND_FEEDBACK_CODE
+# endif
+#endif
+
+#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
+#define IR_FEEDBACK_LED_PIN LED_BUILTIN
+#endif
+
/*
+ * Version 2.2.0 - 7/2024
+ * - New TinyReceiverDecode() function to be used as drop in for IrReceiver.decode().
+ *
* Version 2.1.0 - 2/2024
* - New sendExtendedNEC() function and new parameter aSendNEC2Repeats.
*
diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp
index 19c47bc4a..cd5fe88e8 100644
--- a/src/TinyIRReceiver.hpp
+++ b/src/TinyIRReceiver.hpp
@@ -1,7 +1,7 @@
/*
* TinyIRReceiver.hpp
*
- * Receives IR protocol data of NEC protocol using pin change interrupts.
+ * Receives IR data of NEC protocol using pin change interrupts.
* NEC is the protocol of most cheap remote controls for Arduino.
*
* Parity check is done for address and data.
@@ -28,7 +28,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2024 Armin Joachimsmeyer
+ * Copyright (c) 2022-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -56,13 +56,15 @@
*
* - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input.
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED.
- * - NO_LED_FEEDBACK_CODE Disables the feedback LED function. 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.
+ * - NO_LED_FEEDBACK_CODE Disables the feedback LED function for send and receive. Saves 14 bytes program memory.
+ * - NO_LED_RECEIVE_FEEDBACK_CODE Disables the LED feedback code for receive.
+ * - NO_LED_SEND_FEEDBACK_CODE Disables the LED feedback code for send.
+ * - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory.
+ * - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_ONKYO_PROTOCOL Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
* - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC.
* - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
- * - USE_CALLBACK_FOR_TINY_RECEIVER Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
+ * - USE_CALLBACK_FOR_TINY_RECEIVER Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received.
*/
#ifndef _TINY_IR_RECEIVER_HPP
@@ -70,12 +72,6 @@
#include
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
-#define LOCAL_DEBUG
-#else
-//#define LOCAL_DEBUG // This enables debug output only for this file
-#endif
-
/*
* Protocol selection
*/
@@ -85,7 +81,10 @@
//#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.
-#include "TinyIR.h" // If not defined, it defines IR_RECEIVE_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
+//#define IR_RECEIVE_PIN 2
+//#define NO_LED_RECEIVE_FEEDBACK_CODE // Disables the LED feedback code for receive.
+//#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN
+#include "TinyIR.h"
#include "digitalWriteFast.h"
/** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol
@@ -93,10 +92,13 @@
*/
#if defined(DEBUG)
+#define LOCAL_DEBUG
#define LOCAL_DEBUG_ATTACH_INTERRUPT
#else
-//#define LOCAL_DEBUG_ATTACH_INTERRUPT // to see if attachInterrupt() or static interrupt (by register tweaking) is used
+//#define LOCAL_DEBUG // This enables debug output only for this file
+//#define LOCAL_DEBUG_ATTACH_INTERRUPT // To see if attachInterrupt() or static interrupt (by register tweaking) is used and no other debug output
#endif
+
#if defined(TRACE)
#define LOCAL_TRACE_STATE_MACHINE
#else
@@ -115,21 +117,22 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
#warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
#define IR_RECEIVE_PIN IR_INPUT_PIN
#endif
+
#if !defined(IR_RECEIVE_PIN)
-#if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
+# if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
#define IR_RECEIVE_PIN 10
-#elif defined(__AVR_ATtiny816__)
+# elif defined(__AVR_ATtiny816__)
#warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
#define IR_RECEIVE_PIN 14
-#else
+# else
#warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
#define IR_RECEIVE_PIN 2
-#endif
+# endif
#endif
-#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
-#define IR_FEEDBACK_LED_PIN LED_BUILTIN
+#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
+#define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
#endif
#if !( \
@@ -150,11 +153,9 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData;
* 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 handleTinyReceivedIRData();
+extern void handleReceivedTinyIRData();
-#if defined(LOCAL_DEBUG)
-uint32_t sMicrosOfGap; // The length of the gap before the start bit
-#endif
+uint32_t sMicrosOfGap; // The length of the gap before the start bit, used for trace
/**
* The ISR (Interrupt Service Routine) of TinyIRRreceiver.
* It handles the NEC protocol decoding and calls the user callback function on complete.
@@ -173,8 +174,12 @@ void IRPinChangeInterruptHandler(void) {
*/
uint_fast8_t tIRLevel = digitalReadFast(IR_RECEIVE_PIN);
-#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+#if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, tIRLevel);
+# else
digitalWriteFast(IR_FEEDBACK_LED_PIN, !tIRLevel);
+# endif
#endif
/*
@@ -182,7 +187,7 @@ void IRPinChangeInterruptHandler(void) {
*/
// Repeats can be sent after a pause, which is longer than 64000 microseconds, so we need a 32 bit value for check of repeats
uint32_t tCurrentMicros = micros();
- uint32_t tMicrosOfMarkOrSpace32 = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros;
+ uint32_t tMicrosOfMarkOrSpace32 = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros; // statement is required to force 32 bit arithmetic
uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;
@@ -200,9 +205,9 @@ void IRPinChangeInterruptHandler(void) {
if (tIRLevel == LOW) {
/*
- * We have a mark here
+ * We are at the start of a mark here and tMicrosOfMarkOrSpace is the time of the previous space
*/
- if (tMicrosOfMarkOrSpace > 2 * TINY_RECEIVER_HEADER_MARK) {
+ if (tMicrosOfMarkOrSpace > TINY_RECEIVER_MARK_TIMEOUT) {
// timeout -> must reset state machine
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
}
@@ -210,7 +215,7 @@ void IRPinChangeInterruptHandler(void) {
// We are at the beginning of the header mark, check timing at the next transition
tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
TinyIRReceiverControl.Flags = IRDATA_FLAGS_EMPTY; // If we do it here, it saves 4 bytes
-#if defined(LOCAL_TRACE)
+#if defined(TRACE) // Do not use LOCAL_TRACE here since sMicrosOfGap is read in a cpp file at TRACE
sMicrosOfGap = tMicrosOfMarkOrSpace32;
#endif
#if defined(ENABLE_NEC2_REPEATS)
@@ -227,7 +232,7 @@ void IRPinChangeInterruptHandler(void) {
if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_SPACE)) {
/*
- * We have a valid data header space here -> initialize data
+ * We had a valid data header space before -> initialize data
*/
TinyIRReceiverControl.IRRawDataBitCounter = 0;
#if (TINY_RECEIVER_BITS > 16)
@@ -237,8 +242,9 @@ void IRPinChangeInterruptHandler(void) {
#endif
TinyIRReceiverControl.IRRawDataMask = 1;
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
+
#if !defined(ENABLE_NEC2_REPEATS)
- // Check for NEC repeat header
+ // Alternatively check for NEC repeat header space length
} else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
&& TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS) {
@@ -255,13 +261,17 @@ void IRPinChangeInterruptHandler(void) {
}
}
+
else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
- // Check data space length
+ /*
+ * Start of data mark here, check data space length
+ * Maybe the minimum length check could be removed here.
+ */
if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_ZERO_SPACE)
&& tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_ONE_SPACE)) {
// We have a valid bit here
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
- if (tMicrosOfMarkOrSpace >= 2 * TINY_RECEIVER_UNIT) {
+ if (tMicrosOfMarkOrSpace >= TINY_RECEIVER_ONE_THRESHOLD) {
// we received a 1
#if (TINY_RECEIVER_BITS > 16)
TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
@@ -286,7 +296,8 @@ void IRPinChangeInterruptHandler(void) {
else {
/*
- * We have a space here
+ * We are at the start of a space here and tMicrosOfMarkOrSpace is the time of the previous mark
+ *
*/
if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
/*
@@ -324,7 +335,7 @@ void IRPinChangeInterruptHandler(void) {
* Check address parity
* Address is sent first and contained in the lower word
*/
- if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) {
+ if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t)(~TinyIRReceiverControl.IRRawData.UBytes[1])) {
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set
#else
@@ -337,7 +348,7 @@ void IRPinChangeInterruptHandler(void) {
* Check command parity
*/
#if (TINY_RECEIVER_ADDRESS_BITS > 0)
- if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) {
+ if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t)(~TinyIRReceiverControl.IRRawData.UBytes[3])) {
#if defined(ENABLE_NEC2_REPEATS)
TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED;
#else
@@ -384,7 +395,7 @@ void IRPinChangeInterruptHandler(void) {
// Here we have 8 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[2];
# else
- // Here we have 16 bit command
+ // Here we have 16 bit command
TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord.HighWord;
# endif
@@ -426,6 +437,17 @@ bool isTinyReceiverIdle() {
return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK);
}
+/*
+ * Function to be used as drop in for IrReceiver.decode()
+ */
+bool TinyReceiverDecode() {
+ bool tJustWritten = TinyIRReceiverData.justWritten;
+ if (tJustWritten) {
+ TinyIRReceiverData.justWritten = false;
+ }
+ return tJustWritten;
+}
+
/*
* Checks if IR_RECEIVE_PIN is connected and high
* @return true, if IR Receiver is attached
@@ -444,15 +466,17 @@ bool isIRReceiverAttachedForTinyReceiver() {
bool initPCIInterruptForTinyReceiver() {
pinModeFast(IR_RECEIVE_PIN, INPUT);
-#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+#if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# endif
#endif
return enablePCIInterruptForTinyReceiver();
}
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
@@ -558,14 +582,19 @@ bool enablePCIInterruptForTinyReceiver() {
#if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
# if defined(USE_ATTACH_INTERRUPT)
-#if defined(NOT_AN_INTERRUPT)
+# if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt
if(digitalPinToInterrupt(IR_RECEIVE_PIN) == NOT_AN_INTERRUPT){
return false;
}
-#endif
+# endif
// costs 112 bytes program memory + 4 bytes RAM
+# if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
+ attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here :-(
+# else
attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), IRPinChangeInterruptHandler, CHANGE);
+# endif
# else
+ // USE_ATTACH_INTERRUPT_DIRECT here, only defined for ATtinies *16, see above
// 2.2 us more than version configured with macros and not compatible
attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here
# endif
@@ -573,11 +602,11 @@ bool enablePCIInterruptForTinyReceiver() {
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
Serial.println(F("Use attachInterrupt for pin=" STR(IR_RECEIVE_PIN)));
# endif
-
#else
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
Serial.println(F("Use static interrupt for pin=" STR(IR_RECEIVE_PIN)));
# endif
+
# if defined(USE_INT0)
// interrupt on any logical change
EICRA |= _BV(ISC00);
diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp
index 65a1fe18b..1053d52c7 100644
--- a/src/TinyIRSender.hpp
+++ b/src/TinyIRSender.hpp
@@ -19,7 +19,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2024 Armin Joachimsmeyer
+ * Copyright (c) 2022-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -48,11 +48,13 @@
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
+//#define NO_LED_SEND_FEEDBACK_CODE // Disables the LED feedback code for receive.
+//#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN
#include "TinyIR.h" // Defines protocol timings
#include "digitalWriteFast.h"
@@ -64,6 +66,10 @@
#warning "IR_SEND_PIN is not defined, so it is set to 3"
#define IR_SEND_PIN 3
#endif
+#if !defined(NO_LED_SEND_FEEDBACK_CODE)
+#define LED_SEND_FEEDBACK_CODE // Resolve the double negative
+#endif
+
/*
* Generate 38 kHz IR signal by bit banging
*/
@@ -114,6 +120,15 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) {
void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
+#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# endif
+#endif
+
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
@@ -121,10 +136,10 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
- delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250
+ delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
- delayMicroseconds(NEC_HEADER_SPACE);
+ delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
tData.UWord.LowWord = aAddress;
tData.UWord.HighWord = aCommand;
@@ -132,9 +147,9 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast
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);
+ delayMicroseconds (NEC_ONE_SPACE);
} else {
- delayMicroseconds(NEC_ZERO_SPACE);
+ delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
@@ -153,6 +168,14 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast
}
}
}
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# endif
+#endif
}
/*
@@ -168,6 +191,15 @@ void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# endif
+#endif
+
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
@@ -175,10 +207,10 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
- delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250
+ delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
- delayMicroseconds(NEC_HEADER_SPACE);
+ delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
/*
* The compiler is intelligent and removes the code for "(aAddress > 0xFF)" if we are called with an uint8_t address :-).
@@ -201,9 +233,9 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
sendMark(aSendPin, NEC_BIT_MARK); // constant mark length
if (tData.ULong & 1) {
- delayMicroseconds(NEC_ONE_SPACE);
+ delayMicroseconds (NEC_ONE_SPACE);
} else {
- delayMicroseconds(NEC_ZERO_SPACE);
+ delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
@@ -222,6 +254,14 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
}
}
}
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# endif
+#endif
}
/*
@@ -234,6 +274,15 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_
void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) {
pinModeFast(aSendPin, OUTPUT);
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# endif
+#endif
+
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
@@ -241,10 +290,10 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin
sendMark(aSendPin, NEC_HEADER_MARK);
if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) {
// send the NEC special repeat
- delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250
+ delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250
} else {
// send header
- delayMicroseconds(NEC_HEADER_SPACE);
+ delayMicroseconds (NEC_HEADER_SPACE);
LongUnion tData;
tData.UWord.LowWord = aAddress;
if (aCommand > 0xFF) {
@@ -258,9 +307,9 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin
sendMark(aSendPin, NEC_BIT_MARK); // constant mark length
if (tData.ULong & 1) {
- delayMicroseconds(NEC_ONE_SPACE);
+ delayMicroseconds (NEC_ONE_SPACE);
} else {
- delayMicroseconds(NEC_ZERO_SPACE);
+ delayMicroseconds (NEC_ZERO_SPACE);
}
tData.ULong >>= 1; // shift command for next bit
}
@@ -279,6 +328,14 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin
}
}
}
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# endif
+#endif
}
/*
@@ -294,6 +351,15 @@ void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNum
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) {
pinModeFast(aSendPin, OUTPUT);
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# endif
+#endif
+
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
unsigned long tStartOfFrameMillis = millis();
@@ -337,6 +403,14 @@ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats
}
}
}
+#if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
+ pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT);
+# if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH);
+# else
+ digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW);
+# endif
+#endif
}
/** @}*/
diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h
index 1bb8eb507..faeaa5afd 100644
--- a/src/digitalWriteFast.h
+++ b/src/digitalWriteFast.h
@@ -5,12 +5,22 @@
* by Watterott electronic (www.watterott.com)
* based on https://code.google.com/p/digitalwritefast
*
+ * The value of DigitalReadFast() is the content of the input register e.g. 0x04 for pin2 and NOT always 0 or 1.
+ *
* License: BSD 3-Clause License (https://opensource.org/licenses/BSD-3-Clause)
*/
#ifndef __digitalWriteFast_h_
#define __digitalWriteFast_h_ 1
+//#define THROW_ERROR_IF_NOT_FAST // If activated, an error is thrown if pin is not a compile time constant
+void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") ));
+void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") ));
+void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") ));
+int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") ));
+
+#if !defined(MEGATINYCORE) // megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast().
+
//#define SANGUINO_PINOUT // define for Sanguino pinout
// general macros/defines
@@ -312,28 +322,26 @@
#endif
-
-void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") ));
-void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") ));
-void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") ));
-int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") ));
-
#if !defined(digitalWriteFast)
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalWriteFast(P, V) \
-if (__builtin_constant_p(P)) { \
- BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
-} else { \
+do { \
+ if (__builtin_constant_p(P)) { \
+ BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
+ } else { \
NonConstantsUsedForDigitalWriteFast(); \
-}
+ } \
+} while (0)
# else
#define digitalWriteFast(P, V) \
-if (__builtin_constant_p(P)) { \
- BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
-} else { \
- digitalWrite((P), (V)); \
-}
+do { \
+ if (__builtin_constant_p(P)) { \
+ BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \
+ } else { \
+ digitalWrite((P), (V)); \
+ } \
+} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalWriteFast digitalWrite
@@ -344,28 +352,32 @@ if (__builtin_constant_p(P)) { \
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define pinModeFast(P, V) \
-if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
- if (V == INPUT_PULLUP) {\
- BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
- BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
+do { \
+ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
+ if (V == INPUT_PULLUP) {\
+ BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
+ BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
+ } else { \
+ BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
+ } \
} else { \
- BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
- } \
-} else { \
NonConstantsUsedForPinModeFast(); \
-}
+ } \
+} while (0)
# else
#define pinModeFast(P, V) \
-if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
- if (V == INPUT_PULLUP) {\
- BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
- BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
+do { \
+ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
+ if (V == INPUT_PULLUP) {\
+ BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \
+ BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \
+ } else { \
+ BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
+ } \
} else { \
- BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \
+ pinMode((P), (V)); \
} \
-} else { \
- pinMode((P), (V)); \
-}
+} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define pinModeFast pinMode
@@ -377,17 +389,11 @@ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
// since we have return values, it is easier to implement it by ?:
-#define __digitalReadFast(P ) \
- (__builtin_constant_p(P) ) ? \
- (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
- NonConstantsUsedForDigitalReadFast()
+#define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : NonConstantsUsedForDigitalReadFast() )
# else
#define digitalReadFast(P) ( (int) __digitalReadFast((P)) )
// since we have return values, it is easier to implement it by ?:
-#define __digitalReadFast(P ) \
- (__builtin_constant_p(P) ) ? \
- (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : \
- digitalRead((P))
+#define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : digitalRead((P)) )
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalReadFast digitalRead
@@ -398,22 +404,27 @@ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \
# if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPINReg)
# if defined(THROW_ERROR_IF_NOT_FAST)
#define digitalToggleFast(P) \
-if (__builtin_constant_p(P)) { \
- BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
-} else { \
+do { \
+ if (__builtin_constant_p(P)) { \
+ BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
+ } else { \
NonConstantsUsedForDigitalToggleFast(); \
-}
+ } \
+} while (0)
# else
#define digitalToggleFast(P) \
-if (__builtin_constant_p(P)) { \
- BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
-} else { \
- digitalWrite(P, ! digitalRead(P)); \
-}
+do { \
+ if (__builtin_constant_p(P)) { \
+ BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \
+ } else { \
+ digitalWrite(P, ! digitalRead(P)); \
+ } \
+} while (0)
# endif // defined(THROW_ERROR_IF_NOT_FAST)
# else
#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P))
# endif
#endif // !defined(digitalToggleFast)
+#endif // !defined(MEGATINYCORE)
#endif //__digitalWriteFast_h_
diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp
index 628a5792e..3c1f3015b 100644
--- a/src/ir_BangOlufsen.hpp
+++ b/src/ir_BangOlufsen.hpp
@@ -10,7 +10,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2023 Daniel Wallner and Armin Joachimsmeyer
+ * Copyright (c) 2022-2025 Daniel Wallner and 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
@@ -59,22 +59,22 @@
// If you need to parallel a receiver with another one you may need to delay the signal to get in phase with the other receiver
// 2. A stream of messages can be sent back to back with a new message immediately following the previous stop space
-
// It might be that this only happens over IR and not on the datalink protocol
// You can choose to support this or not:
// Mode 1: Mode with gaps between frames
-// Set RECORD_GAP_MICROS to at least 16000 to accept the unusually long 3. start space
+// Do NOT define ENABLE_BEO_WITHOUT_FRAME_GAP and 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
// 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 :-).
+
+// This treats the 3. start space of 15.5 ms as a gap between 2 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
+// If the receiver is not immediately resumed after the 2 start bit frame, partial second frame will be decoded!
+// Thus 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.
// !!! 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 !!!
@@ -85,7 +85,7 @@
// 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.
+// 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.
/*
@@ -96,11 +96,11 @@
//#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 > 15000
+# if RECORD_GAP_MICROS > 15000 && !defined(SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING)
#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 12750"
# endif
# else
-# if RECORD_GAP_MICROS < 16000
+# if RECORD_GAP_MICROS < 16000 && !defined(SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING)
#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
@@ -111,6 +111,10 @@
#define BEO_UNIT 3125 // All timings are in microseconds
#define BEO_IR_MARK 200 // The length of a mark in the IR protocol
+
+// With decode we see length from 200 to 300 and the 300 leads to errors, if we use 200 as mark length for decode.
+// And the space value is at least 3125, so we can do a reluctant test for the mark anyway.
+#define BEO_IR_MARK_FOR_DECODE 250
#define BEO_DATALINK_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol
#define BEO_PULSE_LENGTH_ZERO BEO_UNIT // The length of a one to zero transition
@@ -147,16 +151,17 @@
/*
* TODO aNumberOfRepeats are handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined
+ * @param aNumberOfHeaderBits default is 8
*/
void IRsend::sendBangOlufsen(uint16_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
- sendBangOlufsenRaw((uint32_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0);
+ sendBangOlufsenRaw((uint32_t(aHeader) << aNumberOfHeaderBits) | aData, aNumberOfHeaderBits + BEO_DATA_BITS, i != 0);
}
}
void IRsend::sendBangOlufsenDataLink(uint32_t aHeader, uint8_t aData, int_fast8_t aNumberOfRepeats, int8_t aNumberOfHeaderBits) {
for (int_fast8_t i = 0; i < aNumberOfRepeats + 1; ++i) {
- sendBangOlufsenRawDataLink((uint64_t(aHeader) << 8) | aData, aNumberOfHeaderBits + 8, i != 0, true);
+ sendBangOlufsenRawDataLink((uint64_t(aHeader) << aNumberOfHeaderBits) | aData, aNumberOfHeaderBits + BEO_DATA_BITS, i != 0, true);
}
}
@@ -293,8 +298,16 @@ static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
bool IRrecv::decodeBangOlufsen() {
#if defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 36) { // 16 bits minimum
+ BEO_DEBUG_PRINT(F("B&O: "));
+ BEO_DEBUG_PRINT(F("Data length="));
+ BEO_DEBUG_PRINT(decodedIRData.rawlen);
+ BEO_DEBUG_PRINTLN(F(" is not < 36 or 6"));
#else
if (decodedIRData.rawlen < 44) { // 16 bits minimum
+ BEO_DEBUG_PRINT(F("B&O: "));
+ BEO_DEBUG_PRINT(F("Data length="));
+ BEO_DEBUG_PRINT(decodedIRData.rawlen);
+ BEO_DEBUG_PRINTLN(F(" is not < 44"));
#endif
return false;
}
@@ -310,7 +323,7 @@ bool IRrecv::decodeBangOlufsen() {
uint8_t tBitNumber = 0;
BEO_TRACE_PRINT(F("Pre gap: "));
- BEO_TRACE_PRINT(decodedIRData.initialGapTicks * 50);
+ BEO_TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50);
BEO_TRACE_PRINT(F(" raw len: "));
BEO_TRACE_PRINTLN(decodedIRData.rawlen);
@@ -319,34 +332,33 @@ bool IRrecv::decodeBangOlufsen() {
* Check if we have the AGC part of the first frame, i.e. start bit 1 and 2.
*/
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));
+ if ((matchMark(irparams.rawbuf[3], BEO_IR_MARK_FOR_DECODE)
+ || matchMark(irparams.rawbuf[3], BEO_DATALINK_MARK))
+ && (matchSpace(irparams.rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK_FOR_DECODE)
+ || matchSpace(irparams.rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_DATALINK_MARK))) {
BEO_TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected"));
} else {
return false; // no B&O protocol
}
} else {
/*
- * Check if leading gap is trailing bit of first frame
+ * Check if leading gap is trailing bit of first AGC frame
*/
if (!matchSpace(decodedIRData.initialGapTicks, 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
+ BEO_TRACE_PRINT(F("B&O: Leading gap of ")); // Leading gap is trailing bit of first frame
+ BEO_TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); // Leading gap is trailing bit of first frame
+ BEO_TRACE_PRINTLN(F(" us 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 (matchMark(irparams.rawbuf[1], BEO_IR_MARK_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_IR_MARK_FOR_DECODE;
+ } else if (matchMark(irparams.rawbuf[1], BEO_DATALINK_MARK)) {
protocolMarkLength = BEO_DATALINK_MARK;
# endif
} else {
- BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_TRACE_PRINTLN(F(": mark length is wrong"));
+ BEO_TRACE_PRINTLN(F("B&O: mark length is wrong"));
return false;
}
@@ -356,8 +368,8 @@ bool IRrecv::decodeBangOlufsen() {
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];
+ uint16_t markLength = irparams.rawbuf[tRawBufferMarkIndex];
+ uint16_t spaceLength = irparams.rawbuf[tRawBufferMarkIndex + 1];
BEO_TRACE_PRINT(tPulseNumber);
BEO_TRACE_PRINT(' ');
@@ -376,29 +388,27 @@ bool IRrecv::decodeBangOlufsen() {
if (tPulseNumber < 4) {
if (tPulseNumber < 2) {
// bit 0 and 1
- if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK)) {
+ if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK_FOR_DECODE)) {
BEO_TRACE_PRINTLN(F(": detected long start bit -> synchronize state now"));
tPulseNumber = 2;
}
} else {
if (tPulseNumber == 3) {
- if (matchMark(markLength, BEO_IR_MARK)) {
+ if (matchMark(markLength, BEO_IR_MARK_FOR_DECODE)) {
# if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
- protocolMarkLength = BEO_IR_MARK;
+ protocolMarkLength = BEO_IR_MARK_FOR_DECODE;
} else if (matchMark(markLength, BEO_DATALINK_MARK)) {
protocolMarkLength = BEO_DATALINK_MARK;
# endif
} else {
- BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_DEBUG_PRINTLN(F(": 4. (start) mark length is wrong"));
+ BEO_DEBUG_PRINTLN(F("B&O: 4. (start) mark length is wrong"));
return false;
}
}
// bit 2 and 3
if (!matchBeoLength(markLength + spaceLength,
(tPulseNumber == 2) ? BEO_PULSE_LENGTH_START_BIT : BEO_PULSE_LENGTH_ZERO)) {
- BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_DEBUG_PRINTLN(F(": Start length is wrong"));
+ BEO_DEBUG_PRINTLN(F("B&O: Start length is wrong"));
return false;
}
}
@@ -412,10 +422,9 @@ bool IRrecv::decodeBangOlufsen() {
#if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE)
if (!matchMark(markLength, protocolMarkLength)) {
#else
- if (!matchMark(markLength, BEO_IR_MARK)) {
+ if (!matchMark(markLength, BEO_IR_MARK_FOR_DECODE)) {
#endif
- BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_DEBUG_PRINTLN(F(": Mark length is wrong"));
+ BEO_DEBUG_PRINTLN(F("B&O: Mark length is wrong"));
return false;
}
@@ -424,14 +433,12 @@ bool IRrecv::decodeBangOlufsen() {
*/
if (tBitNumber > BEO_DATA_BITS + 4) {
if (matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_TRAILING_BIT)) {
- BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_DEBUG_PRINTLN(F(": Trailing bit detected"));
+ BEO_DEBUG_PRINTLN(F("B&O: Trailing bit detected"));
break;
}
#if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP)
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"));
+ BEO_DEBUG_PRINTLN(F("B&O: End of buffer, but no trailing bit detected"));
return false;
}
#endif
@@ -445,8 +452,7 @@ bool IRrecv::decodeBangOlufsen() {
} else if (tLastDecodedBitValue == 1 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ZERO)) {
tLastDecodedBitValue = 0;
} else if (!matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_EQUAL)) {
- BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN));
- BEO_DEBUG_PRINT(F(": Index="));
+ BEO_DEBUG_PRINT(F("B&O: Index="));
BEO_DEBUG_PRINT(tRawBufferMarkIndex);
BEO_DEBUG_PRINT(F(" Length "));
BEO_DEBUG_PRINT((markLength + spaceLength) * MICROS_PER_TICK);
@@ -471,8 +477,7 @@ bool IRrecv::decodeBangOlufsen() {
* Check for last bit after decoding it
*/
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"));
+ BEO_TRACE_PRINTLN(F("B&O: Last bit reached"));
break;
}
#endif
diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp
index c8ec9b7a1..b278d1f0c 100644
--- a/src/ir_BoseWave.hpp
+++ b/src/ir_BoseWave.hpp
@@ -9,7 +9,7 @@
#ifndef _IR_BOSEWAVE_HPP
#define _IR_BOSEWAVE_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -46,9 +46,9 @@
#define BOSEWAVE_REPEAT_DISTANCE 50000
#define BOSEWAVE_MAXIMUM_REPEAT_DISTANCE 62000
-struct PulseDistanceWidthProtocolConstants BoseWaveProtocolConstants = { BOSEWAVE, BOSEWAVE_KHZ, BOSEWAVE_HEADER_MARK,
-BOSEWAVE_HEADER_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST
- , (BOSEWAVE_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
+struct PulseDistanceWidthProtocolConstants const BoseWaveProtocolConstants PROGMEM = {BOSEWAVE, BOSEWAVE_KHZ, BOSEWAVE_HEADER_MARK,
+ BOSEWAVE_HEADER_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ONE_SPACE, BOSEWAVE_BIT_MARK, BOSEWAVE_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE
+ , (BOSEWAVE_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr};
/************************************
* Start of send and decode functions
@@ -58,12 +58,12 @@ void IRsend::sendBoseWave(uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
// send 8 command bits and then 8 inverted command bits LSB first
uint16_t tData = ((~aCommand) << 8) | aCommand;
- sendPulseDistanceWidth(&BoseWaveProtocolConstants, tData, BOSEWAVE_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidth_P(&BoseWaveProtocolConstants, tData, BOSEWAVE_BITS, aNumberOfRepeats);
}
bool IRrecv::decodeBoseWave() {
- if (!checkHeader(&BoseWaveProtocolConstants)) {
+ if (!checkHeader_P(&BoseWaveProtocolConstants)) {
return false;
}
@@ -76,16 +76,10 @@ bool IRrecv::decodeBoseWave() {
return false;
}
- if (!decodePulseDistanceWidthData(&BoseWaveProtocolConstants, BOSEWAVE_BITS)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Bose: "));
- Serial.println(F("Decode failed"));
-#endif
- return false;
- }
+ decodePulseDistanceWidthData_P(&BoseWaveProtocolConstants, BOSEWAVE_BITS);
// Stop bit
- if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * BOSEWAVE_BITS)], BOSEWAVE_BIT_MARK)) {
+ if (!matchMark(irparams.rawbuf[3 + (2 * BOSEWAVE_BITS)], BOSEWAVE_BIT_MARK)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Bose: "));
Serial.println(F("Stop bit mark length is wrong"));
diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp
index f22141145..69827fefb 100644
--- a/src/ir_Denon.hpp
+++ b/src/ir_Denon.hpp
@@ -32,7 +32,7 @@
#ifndef _IR_DENON_HPP
#define _IR_DENON_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -82,7 +82,7 @@
* 000A 0046 000A 0046 000A 001E 000A 001E 000A 001E 000A 0046 000A 001E 000A 001E // 8 inverted command bits
* 000A 0046 000A 0046 000A 0679 // 2 frame bits 1,1 + stop bit + space for Repeat
* From analyzing the codes for Tuner preset 1 to 8 in tab Main Zone ID#1 it is obvious, that the protocol is LSB first at least for command.
- * All Denon codes with 32 as 3. value use the Kaseyikyo Denon variant.
+ * All Denon codes with 32 as 3. value use the Kaseikyo Denon variant.
*/
// LSB first, no start bit, 5 address + 8 command + 2 frame (0,0) + 1 stop bit - each frame 2 times
// Every frame is auto repeated with a space period of 45 ms and the command and frame inverted to (1,1) or (0,1) for SHARP.
@@ -105,47 +105,61 @@
#define DENON_HEADER_MARK DENON_UNIT // The length of the Header:Mark
#define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space
-struct PulseDistanceWidthProtocolConstants DenonProtocolConstants = { DENON, DENON_KHZ, DENON_HEADER_MARK, DENON_HEADER_SPACE,
-DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST,
- (DENON_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
+struct PulseDistanceWidthProtocolConstants const DenonProtocolConstants PROGMEM = {DENON, DENON_KHZ, DENON_HEADER_MARK, DENON_HEADER_SPACE,
+ DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE,
+ (DENON_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr};
/************************************
* Start of send and decode functions
************************************/
void IRsend::sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
- sendDenon(aAddress, aCommand, aNumberOfRepeats, true);
+ sendDenon(aAddress, aCommand, aNumberOfRepeats, 1);
+ // see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/1272
}
-void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aSendSharp) {
+void IRsend::sendSharp2(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
+ sendDenon(aAddress, aCommand, aNumberOfRepeats, 2);
+}
+
+/*
+ * Denon frames are always sent 3 times. A non inverted (normal), an inverted frame, ending with a normal frame.
+ * Repeats are done by just adding an inverted and a normal frame with no extra delay, so it is quite responsible :-)
+ * If you specify a repeat of e.g. 3, then 3 + 6 frames are sent.
+ * Measured at Denon RC 1081.
+ */
+void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aSendSharpFrameMarker) {
// Set IR carrier frequency
enableIROut (DENON_KHZ); // 38 kHz
// Add frame marker for sharp
uint16_t tCommand = aCommand;
- if (aSendSharp) {
- tCommand |= 0x0200; // the 2 upper bits are 00 for Denon and 10 for Sharp
- }
+ // see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/1272
+ tCommand |= aSendSharpFrameMarker << 8; // the 2 upper bits are 00 for Denon and 01 or 10 for Sharp
+
uint16_t tData = aAddress | ((uint16_t) tCommand << DENON_ADDRESS_BITS);
- uint16_t tInvertedData = (tData ^ 0x7FE0); // Command and frame (upper 10 bits) are inverted
+ uint16_t tInvertedData = (tData ^ 0x7FE0); // Command and frame (upper 10 bits, bit 5 to 14) are inverted
uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
while (tNumberOfCommands > 0) {
// Data
- sendPulseDistanceWidthData(&DenonProtocolConstants, tData, DENON_BITS);
+ sendPulseDistanceWidthData_P(&DenonProtocolConstants, tData, DENON_BITS);
// Inverted autorepeat frame
delay(DENON_AUTO_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
- sendPulseDistanceWidthData(&DenonProtocolConstants, tInvertedData, DENON_BITS);
+ sendPulseDistanceWidthData_P(&DenonProtocolConstants, tInvertedData, DENON_BITS);
tNumberOfCommands--;
- // skip last delay!
- if (tNumberOfCommands > 0) {
- // send repeated command with a fixed space gap
- delay( DENON_AUTO_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
- }
+ // send repeated command with a fixed space gap
+ delay( DENON_AUTO_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI);
}
+ /*
+ * always end with a normal frame
+ * skip last delay!
+ */
+ sendPulseDistanceWidthData_P(&DenonProtocolConstants, tData, DENON_BITS);
+
}
bool IRrecv::decodeSharp() {
@@ -165,16 +179,10 @@ bool IRrecv::decodeDenon() {
}
// Try to decode as Denon protocol
- if (!decodePulseDistanceWidthData(&DenonProtocolConstants, DENON_BITS, 1)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Denon: "));
- Serial.println(F("Decode failed"));
-#endif
- return false;
- }
+ decodePulseDistanceWidthData_P(&DenonProtocolConstants, DENON_BITS, 1);
- // Check for stop mark
- if (!matchMark(decodedIRData.rawDataPtr->rawbuf[(2 * DENON_BITS) + 1], DENON_HEADER_MARK)) {
+ // Check for stop mark, this stop bit distinguishes it from decoding as Sony
+ if (!matchMark(irparams.rawbuf[(2 * DENON_BITS) + 1], DENON_HEADER_MARK)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("Denon: "));
Serial.println(F("Stop bit mark length is wrong"));
@@ -190,49 +198,53 @@ bool IRrecv::decodeDenon() {
// Check for (auto) repeat
if (decodedIRData.initialGapTicks < ((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;
- }
+ decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
- if (tFrameBits & 0x01) {
+ repeatCount++;
+ /*
+ * 1. repeat is inverted autorepeat -> IRDATA_FLAGS_IS_AUTO_REPEAT
+ * 2. repeat is normal autorepeat (end) or 1. normal repeat -> IRDATA_FLAGS_IS_AUTO_REPEAT
+ * 3. repeat is inverted autorepeat of the 1. repeat -> IRDATA_FLAGS_IS_REPEAT (not the correct frame, but this enables easy counting of repeats)
+ * 4. repeat is normal autorepeat (end) or 2. normal repeat -> IRDATA_FLAGS_IS_AUTO_REPEAT
+ * 5. repeat is inverted autorepeat of the 2. repeat -> IRDATA_FLAGS_IS_REPEAT (not the correct frame, but this enables easy counting of repeats)
+ * 6. repeat is normal autorepeat (end) or 3. normal repeat -> IRDATA_FLAGS_IS_AUTO_REPEAT
+ */
+
+ if (repeatCount & 0x01) {
/*
- * Here we are in the auto repeated frame with the inverted command
+ * Here we are in an inverted auto repeated frame where the command and frame bits are inverted
*/
#if defined(LOCAL_DEBUG)
- Serial.print(F("Denon: "));
- Serial.println(F("Autorepeat received="));
+ Serial.print(F("Denon: Inverted frame"));
#endif
- decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
+ if (repeatCount > 1) { // skip first auto repeat
+ decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT;
+ }
// Check parity of consecutive received commands. There is no parity in one data set.
if ((uint8_t) lastDecodedCommand != (uint8_t)(~decodedIRData.command)) {
decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED;
#if defined(LOCAL_DEBUG)
- Serial.print(F("Denon: "));
- Serial.print(F("Parity check for repeat failed. Last command="));
- Serial.print(lastDecodedCommand, HEX);
+ Serial.print(F("Denon: Parity check of inverted with non inverted frame failed. Last command="));
+ Serial.print((uint8_t)lastDecodedCommand, HEX);
Serial.print(F(" current="));
- Serial.println(~decodedIRData.command, HEX);
+ Serial.println((uint8_t)~decodedIRData.command, HEX);
#endif
}
// always take non inverted command
decodedIRData.command = lastDecodedCommand;
- }
- // repeated command here
- if (tFrameBits == 1 || tFrameBits == 2) {
- decodedIRData.protocol = SHARP;
- } else {
- decodedIRData.protocol = DENON;
+ // inverted command here, re-invert the frame bits for later protocol decoding
+ tFrameBits = tFrameBits ^ 0x03;
}
} else {
- repeatCount = 0;
// first command here
- if (tFrameBits == 2) {
- decodedIRData.protocol = SHARP;
- } else {
- decodedIRData.protocol = DENON;
- }
+ repeatCount = 0;
+ }
+
+ if (tFrameBits) {
+ decodedIRData.protocol = SHARP;
+ } else {
+ decodedIRData.protocol = DENON;
}
decodedIRData.numberOfBits = DENON_BITS;
@@ -274,7 +286,7 @@ void IRsend::sendDenon(unsigned long data, int nbits) {
* Old function without parameter aNumberOfRepeats
*/
void IRsend::sendSharp(uint16_t aAddress, uint16_t aCommand) {
- sendDenon(aAddress, aCommand, true, 0);
+ sendDenon(aAddress, aCommand, 0, true);
}
bool IRrecv::decodeDenonOld(decode_results *aResults) {
@@ -294,9 +306,7 @@ bool IRrecv::decodeDenonOld(decode_results *aResults) {
}
// Try to decode as Denon protocol.
- if (!decodePulseDistanceWidthData(DENON_BITS, 3, DENON_BIT_MARK, DENON_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) {
- return false;
- }
+ decodePulseDistanceWidthData(DENON_BITS, 3, DENON_BIT_MARK, DENON_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST);
// Success
aResults->value = decodedIRData.decodedRawData;
diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp
index aa2d4ed24..d7a7a9cd8 100644
--- a/src/ir_DistanceWidthProtocol.hpp
+++ b/src/ir_DistanceWidthProtocol.hpp
@@ -34,7 +34,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2022-2024 Armin Joachimsmeyer
+ * Copyright (c) 2022-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -62,11 +62,12 @@
#define DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS 100000 // 100 ms, bit it is just a guess
#endif
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
+//#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints errors which prevents data to be decoded as distance width data
#if !defined(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE)
# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
@@ -192,23 +193,29 @@ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIn
* 3. Try to decode with the mark and space data found in step 1
* No data and address decoding, only raw data as result.
*
+ * Restrictions:
+ * Only protocols with at least 7 bits (+ start and trailing stop bit) are accepted.
+ * Pulse or pause duration must be below 2500 us (depends on DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE).
+ *
* calloc() version is 700 bytes larger :-(
*/
bool IRrecv::decodeDistanceWidth() {
/*
* Array for up to 49 ticks / 2500 us (or 199 ticks / 10 ms us if RAM > 2k)
- * 0 tick covers mark or space durations from 0 to 49 us, and 49 ticks from 2450 to 2499 us
+ * tick array index 0 covers mark or space durations from 0 to 49 us, and index 49 from 2450 to 2499 us
*/
uint8_t tDurationArray[DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE];
/*
- * Accept only protocols with at least 7 bits
+ * Only protocols with at least 7 bits are accepted
*/
if (decodedIRData.rawlen < (2 * 7) + 4) {
- IR_DEBUG_PRINT(F("PULSE_DISTANCE_WIDTH: "));
- IR_DEBUG_PRINT(F("Data length="));
- IR_DEBUG_PRINT(decodedIRData.rawlen);
- IR_DEBUG_PRINTLN(F(" is less than 18"));
+#if defined(DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
+ Serial.print(F("PULSE_DISTANCE_WIDTH: "));
+ Serial.print(F("Data length="));
+ Serial.print(decodedIRData.rawlen);
+ Serial.println(F(" is less than 18"));
+#endif
return false;
}
@@ -220,14 +227,14 @@ bool IRrecv::decodeDistanceWidth() {
* Count number of mark durations. Skip leading start and trailing stop bit.
*/
for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) {
- auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tDurationTicks = irparams.rawbuf[i];
if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) {
tDurationArray[tDurationTicks]++; // count duration if less than DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE
if (tIndexOfMaxDuration < tDurationTicks) {
tIndexOfMaxDuration = tDurationTicks;
}
} else {
-#if defined(LOCAL_DEBUG)
+#if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.print(F("Mark "));
Serial.print(tDurationTicks * MICROS_PER_TICK);
@@ -252,7 +259,7 @@ bool IRrecv::decodeDistanceWidth() {
#endif
if (!tSuccess) {
-#if defined(LOCAL_DEBUG)
+#if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.println(F("Mark aggregation failed, more than 2 distinct mark duration values found"));
#endif
@@ -267,14 +274,14 @@ bool IRrecv::decodeDistanceWidth() {
*/
tIndexOfMaxDuration = 0;
for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) {
- auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i];
+ auto tDurationTicks = irparams.rawbuf[i];
if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) {
tDurationArray[tDurationTicks]++;
if (tIndexOfMaxDuration < tDurationTicks) {
tIndexOfMaxDuration = tDurationTicks;
}
} else {
-#if defined(LOCAL_DEBUG)
+#if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.print(F("Space "));
Serial.print(tDurationTicks * MICROS_PER_TICK);
@@ -299,72 +306,83 @@ bool IRrecv::decodeDistanceWidth() {
#endif
if (!tSuccess) {
-#if defined(LOCAL_DEBUG)
+#if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
Serial.print(F("PULSE_DISTANCE_WIDTH: "));
Serial.println(F("Space aggregation failed, more than 2 distinct space duration values found"));
#endif
return false;
}
+#if RAW_BUFFER_LENGTH <= (512 -4)
+ uint_fast8_t tNumberOfBits;
+#else
+ uint16_t tNumberOfBits;
+#endif
+ tNumberOfBits = (decodedIRData.rawlen / 2) - 1;
+ if (tSpaceTicksLong > 0) {
+ // For PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- a stop bit is mandatory, for PULSE_WIDTH it is not required!
+ tNumberOfBits--; // Correct for PULSE_DISTANCE stop bit
+ }
+ decodedIRData.numberOfBits = tNumberOfBits;
+
/*
* Print characteristics of this protocol. Durations are in (50 us) ticks.
* Number of bits, start bit, start pause, long mark, long space, short mark, short space
*
- * NEC: 32, 180, 90, 0, 34, 11, 11
- * Samsung32: 32, 90, 90, 0, 34, 11, 11
- * LG: 28, 180, 84, 0, 32, 10, 11
- * JVC: 16, 168, 84, 0, 32, 10, 10
- * Kaseikyo: 48. 69, 35, 0, 26, 9, 9
- * Sony: 12|15|20, 48, 12, 24, 0, 12, 12 // the only known pulse width protocol
+ * NEC: 32, 180, 90, 11, 34, 11, 11
+ * Samsung32: 32, 90, 90, 11, 34, 11, 11
+ * LG: 28, 180, 84, 10, 32, 10, 11
+ * JVC: 16, 168, 84, 10, 32, 10, 10
+ * Kaseikyo: 48. 69, 35, 9, 26, 9, 9
+ * Sony: 12|15|20, 48, 12, 24, 12, 12, 12 // the only known pulse width protocol
* Disney monorail
* model: 7, 120, 10, 30, 30, 10, 10 // PulseDistanceWidth. Can be seen as direct conversion of a 7 bit serial timing at 250 baud with a 6 ms start bit.
*/
#if defined(LOCAL_DEBUG)
Serial.print(F("DistanceWidthTimingInfoStruct: "));
- Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
+ Serial.print(tNumberOfBits);
Serial.print(F(", "));
- Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
+ Serial.print(irparams.rawbuf[1] * MICROS_PER_TICK);
Serial.print(F(", "));
- Serial.print(tMarkTicksLong * MICROS_PER_TICK);
+ Serial.print(irparams.rawbuf[2] * MICROS_PER_TICK);
Serial.print(F(", "));
- Serial.print(tSpaceTicksLong * MICROS_PER_TICK);
+ if(tMarkTicksLong == 0) {
+ Serial.print(tMarkTicksShort * MICROS_PER_TICK);
+ } else {
+ Serial.print(tMarkTicksLong * MICROS_PER_TICK);
+ }
+ Serial.print(F(", "));
+ if(tSpaceTicksLong == 0) {
+ Serial.print(tSpaceTicksShort * MICROS_PER_TICK);
+ } else {
+ Serial.print(tSpaceTicksLong * MICROS_PER_TICK);
+ }
Serial.print(F(", "));
Serial.print(tMarkTicksShort * MICROS_PER_TICK);
Serial.print(F(", "));
Serial.println(tSpaceTicksShort * MICROS_PER_TICK);
#endif
-#if RAW_BUFFER_LENGTH <= (512 -4)
- uint_fast8_t tNumberOfBits;
-#else
- uint16_t tNumberOfBits;
-#endif
- tNumberOfBits = (decodedIRData.rawlen / 2) - 1;
- if (tSpaceTicksLong > 0) {
- // For PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- a stop bit is mandatory, for PULSE_WIDTH it is not required!
- tNumberOfBits--; // Correct for stop bit
- }
- decodedIRData.numberOfBits = tNumberOfBits;
+
uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE;
/*
* We can have the following protocol timings
* PULSE_DISTANCE: Pause/spaces have different length and determine the bit value, longer space is 1. Pulses/marks can be constant, like NEC.
* PULSE_WIDTH: Pulses/marks have different length and determine the bit value, longer mark is 1. Pause/spaces can be constant, like Sony.
- * PULSE_DISTANCE_WIDTH: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. Can be decoded by PULSE_DISTANCE decoder.
+ * PULSE_DISTANCE_WIDTH: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. Can be decoded by PULSE_DISTANCE approach.
*/
if (tMarkTicksLong == 0 && tSpaceTicksLong == 0) {
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_DISTANCE: "));
- Serial.println(F("Only 1 distinct duration value for each space and mark found"));
+ Serial.println(F("Cannot decode, because there is only one distinct duration value for each space and mark"));
#endif
return false;
}
unsigned int tSpaceMicrosShort;
-#if defined DECODE_STRICT_CHECKS
+#if defined(LOCAL_DEBUG)
if(tMarkTicksLong > 0 && tSpaceTicksLong > 0) {
- // We have different mark and space length here, so signal decodePulseDistanceWidthData() not to check against constant length decodePulseDistanceWidthData
- tSpaceMicrosShort = 0;
+ Serial.println(F("PULSE_DISTANCE_WIDTH signal found"));
}
#endif
tSpaceMicrosShort = tSpaceTicksShort * MICROS_PER_TICK;
@@ -381,44 +399,48 @@ bool IRrecv::decodeDistanceWidth() {
if (tNumberOfBitsForOneDecode > BITS_IN_RAW_DATA_TYPE) {
tNumberOfBitsForOneDecode = BITS_IN_RAW_DATA_TYPE;
}
- bool tResult;
if (tSpaceTicksLong > 0) {
/*
- * Here short and long space durations found.
- * Since parameters aOneMarkMicros and aOneSpaceMicros are equal, we only check tSpaceMicrosLong here.
+ * Here short and long space durations found. So we have PULSE_DISTANCE or PULSE_DISTANCE_WIDTH.
+ * PULSE_DISTANCE_WIDTH can successfully be decoded by only using the timings of space :-).
*/
- decodedIRData.protocol = PULSE_DISTANCE; // Sony + PULSE_DISTANCE_WIDTH
- tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosShort, tSpaceMicrosLong,
- tMarkMicrosShort,
+ decodedIRData.protocol = PULSE_DISTANCE; // NEC etc. + PULSE_DISTANCE_WIDTH
+#if defined(USE_THRESHOLD_DECODER)
+ decodeWithThresholdPulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex,
+ ((tSpaceMicrosLong + tSpaceMicrosShort) / 2) + MARK_EXCESS_MICROS, // MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
+#else
+ decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tSpaceMicrosLong,
+#endif
+ PROTOCOL_IS_PULSE_DISTANCE,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- true
+ PROTOCOL_IS_MSB_FIRST
#else
- false
+ PROTOCOL_IS_LSB_FIRST
#endif
);
+
} else {
/*
- * Here no long space duration found. => short and long mark durations found, check tMarkMicrosLong here
+ * Here no long space duration but short and long mark durations found. So we have PULSE_WIDTH.
+ * Use timing of marks for decoding here.
* This else case will most likely never be used, but it only requires 12 bytes additional programming space :-)
*/
- decodedIRData.protocol = PULSE_WIDTH; // NEC etc.
- tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong, tSpaceMicrosShort,
- tMarkMicrosShort,
+ decodedIRData.protocol = PULSE_WIDTH; // Sony
+#if defined(USE_THRESHOLD_DECODER)
+ decodeWithThresholdPulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex,
+ ((tMarkMicrosLong+ tMarkMicrosShort) / 2) - MARK_EXCESS_MICROS, // MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
+#else
+ decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong,
+#endif
+ PROTOCOL_IS_PULSE_WIDTH,
#if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
- true
+ PROTOCOL_IS_MSB_FIRST
#else
- false
+ PROTOCOL_IS_LSB_FIRST
#endif
);
}
- if (!tResult) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("PULSE_WIDTH: "));
- Serial.println(F("Decode failed"));
-#endif
- return false;
- }
#if defined(LOCAL_DEBUG)
Serial.print(F("PULSE_WIDTH: "));
Serial.print(F("decodedRawData=0x"));
@@ -434,14 +456,18 @@ bool IRrecv::decodeDistanceWidth() {
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
#endif
- // Check for repeat
- checkForRepeatSpaceTicksAndSetFlag(DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS / MICROS_PER_TICK);
+ // Check for repeat. Check also for equality of last DecodedRawData.
+ if (decodedIRData.initialGapTicks < DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS / MICROS_PER_TICK
+ && decodedIRData.decodedRawDataArray[tNumberOfAdditionalArrayValues] == lastDecodedRawData) {
+ decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT;
+ }
+ lastDecodedRawData = decodedIRData.decodedRawData;
/*
* Store timing data to reproduce frame for sending
*/
- decodedIRData.DistanceWidthTimingInfo.HeaderMarkMicros = (decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK);
- decodedIRData.DistanceWidthTimingInfo.HeaderSpaceMicros = (decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK);
+ decodedIRData.DistanceWidthTimingInfo.HeaderMarkMicros = (irparams.rawbuf[1] * MICROS_PER_TICK);
+ decodedIRData.DistanceWidthTimingInfo.HeaderSpaceMicros = (irparams.rawbuf[2] * MICROS_PER_TICK);
decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosShort;
decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosShort;
if (tMarkMicrosLong != 0) {
diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp
index f9ea167cd..81c7281a3 100644
--- a/src/ir_FAST.hpp
+++ b/src/ir_FAST.hpp
@@ -35,7 +35,7 @@
#include "TinyIR.h"
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -54,18 +54,18 @@
//==============================================================================
#include "TinyIR.h"
/*
-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
-*/
-struct PulseDistanceWidthProtocolConstants FASTProtocolConstants = { FAST, FAST_KHZ, FAST_HEADER_MARK, FAST_HEADER_SPACE,
-FAST_BIT_MARK, FAST_ONE_SPACE, FAST_BIT_MARK, FAST_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (FAST_REPEAT_PERIOD / MICROS_IN_ONE_MILLI),
-NULL };
+ Sum: 28900
+ */
+struct PulseDistanceWidthProtocolConstants const FASTProtocolConstants PROGMEM = { FAST, FAST_KHZ, FAST_HEADER_MARK,
+FAST_HEADER_SPACE, FAST_BIT_MARK, FAST_ONE_SPACE, FAST_BIT_MARK, FAST_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST
+ | PROTOCOL_IS_PULSE_DISTANCE, (FAST_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr };
/************************************
* Start of send and decode functions
@@ -84,7 +84,7 @@ void IRsend::sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats) {
mark(FAST_HEADER_MARK);
space(FAST_HEADER_SPACE);
- sendPulseDistanceWidthData(&FASTProtocolConstants, aCommand | (((uint8_t)(~aCommand)) << 8), FAST_BITS);
+ sendPulseDistanceWidthData_P(&FASTProtocolConstants, aCommand | (((uint8_t)(~aCommand)) << 8), FAST_BITS);
tNumberOfCommands--;
// skip last delay!
@@ -108,26 +108,19 @@ bool IRrecv::decodeFAST() {
return false;
}
- if (!checkHeader(&FASTProtocolConstants)) {
- return false;
- }
-
- if (!decodePulseDistanceWidthData(&FASTProtocolConstants, FAST_BITS)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("FAST: "));
- Serial.println(F("Decode failed"));
-#endif
+ if (!checkHeader_P(&FASTProtocolConstants)) {
return false;
}
+ decodePulseDistanceWidthData_P(&FASTProtocolConstants, FAST_BITS);
WordUnion tValue;
tValue.UWord = decodedIRData.decodedRawData;
- if (tValue.UByte.LowByte != (uint8_t)~(tValue.UByte.HighByte)) {
+ if (tValue.UByte.LowByte != (uint8_t) ~(tValue.UByte.HighByte)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("FAST: "));
Serial.print(F("8 bit parity is not correct. Expected=0x"));
- Serial.print((uint8_t)~(tValue.UByte.LowByte), HEX);
+ Serial.print((uint8_t) ~(tValue.UByte.LowByte), HEX);
Serial.print(F(" received=0x"));
Serial.print(tValue.UByte.HighByte, HEX);
Serial.print(F(" data=0x"));
diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp
index 614cc00c7..500b91641 100644
--- a/src/ir_JVC.hpp
+++ b/src/ir_JVC.hpp
@@ -32,7 +32,7 @@
#ifndef _IR_JVC_HPP
#define _IR_JVC_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -62,7 +62,8 @@
// IRP: {38k,525}<1,-1|1,-3>(16,-8,(D:8,F:8,1,-45)+)
// LSB first, 1 start bit + 8 bit address + 8 bit command + 1 stop bit.
// The JVC protocol repeats by skipping the header mark and space -> this leads to a poor repeat detection for JVC protocol.
-// Some JVC devices require to send 3 repeats. https://github.com/Arduino-IRremote/Arduino-IRremote/issues/21
+// Some JVC devices require to send 3 repeats.
+
#define JVC_ADDRESS_BITS 8 // 8 bit address
#define JVC_COMMAND_BITS 8 // Command
@@ -79,8 +80,8 @@
#define JVC_REPEAT_DISTANCE (uint16_t)(45 * JVC_UNIT) // 23625 - Commands are repeated with a distance of 23 ms for as long as the key on the remote control is held down.
#define JVC_REPEAT_PERIOD 65000 // assume around 40 ms for a JVC frame. JVC IR Remotes: RM-SA911U, RM-SX463U have 45 ms period
-struct PulseDistanceWidthProtocolConstants JVCProtocolConstants = { JVC, JVC_KHZ, JVC_HEADER_MARK, JVC_HEADER_SPACE, JVC_BIT_MARK,
-JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
+struct PulseDistanceWidthProtocolConstants const JVCProtocolConstants PROGMEM = {JVC, JVC_KHZ, JVC_HEADER_MARK, JVC_HEADER_SPACE, JVC_BIT_MARK,
+ JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr};
/************************************
* Start of send and decode functions
@@ -105,7 +106,7 @@ void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe
while (tNumberOfCommands > 0) {
// Address + command
- sendPulseDistanceWidthData(&JVCProtocolConstants, aAddress | (aCommand << JVC_ADDRESS_BITS), JVC_BITS);
+ sendPulseDistanceWidthData_P(&JVCProtocolConstants, aAddress | (aCommand << JVC_ADDRESS_BITS), JVC_BITS);
tNumberOfCommands--;
// skip last delay!
@@ -136,8 +137,8 @@ bool IRrecv::decodeJVC() {
* Check leading space and first and last mark length
*/
if (decodedIRData.initialGapTicks < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK))
- && matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_BIT_MARK)
- && matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawlen - 1], JVC_BIT_MARK)) {
+ && matchMark(irparams.rawbuf[1], JVC_BIT_MARK)
+ && matchMark(irparams.rawbuf[decodedIRData.rawlen - 1], JVC_BIT_MARK)) {
/*
* We have a repeat here, so do not check for start bit
*/
@@ -148,19 +149,12 @@ bool IRrecv::decodeJVC() {
}
} else {
- if (!checkHeader(&JVCProtocolConstants)) {
+ if (!checkHeader_P(&JVCProtocolConstants)) {
return false;
}
- if (!decodePulseDistanceWidthData(&JVCProtocolConstants, JVC_BITS)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("JVC: "));
- Serial.println(F("Decode failed"));
-#endif
- return false;
- }
+ decodePulseDistanceWidthData_P(&JVCProtocolConstants, JVC_BITS);
- // Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
decodedIRData.command = decodedIRData.decodedRawData >> JVC_ADDRESS_BITS; // upper 8 bits of LSB first value
decodedIRData.address = decodedIRData.decodedRawData & 0xFF; // lowest 8 bit of LSB first value
@@ -207,9 +201,7 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) {
}
offset++;
- if (!decodePulseDistanceWidthData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) {
- return false;
- }
+ decodePulseDistanceWidthData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST);
// Stop bit
if (!matchMark(aResults->rawbuf[offset + (2 * JVC_BITS)], JVC_BIT_MARK)) {
diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp
index fe61f63e1..fa1086851 100644
--- a/src/ir_Kaseikyo.hpp
+++ b/src/ir_Kaseikyo.hpp
@@ -32,7 +32,7 @@
#ifndef _IR_KASEIKYO_HPP
#define _IR_KASEIKYO_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -118,9 +118,9 @@
#define SHARP_VENDOR_ID_CODE 0x5AAA
#define JVC_VENDOR_ID_CODE 0x0103
-struct PulseDistanceWidthProtocolConstants KaseikyoProtocolConstants = { KASEIKYO, KASEIKYO_KHZ, KASEIKYO_HEADER_MARK,
-KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST
- , (KASEIKYO_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL };
+struct PulseDistanceWidthProtocolConstants const KaseikyoProtocolConstants PROGMEM = {KASEIKYO, KASEIKYO_KHZ, KASEIKYO_HEADER_MARK,
+ KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE
+ , (KASEIKYO_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr};
/************************************
* Start of send and decode functions
@@ -146,7 +146,7 @@ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumb
IRRawDataType tRawKaseikyoData[2];
tRawKaseikyoData[0] = (uint32_t) tSendValue.UWord.LowWord << 16 | aVendorCode; // LSB of tRawKaseikyoData[0] is sent first
tRawKaseikyoData[1] = tSendValue.UWord.HighWord;
- sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawKaseikyoData[0], KASEIKYO_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidthFromArray_P(&KaseikyoProtocolConstants, &tRawKaseikyoData[0], KASEIKYO_BITS, aNumberOfRepeats);
#else
LongLongUnion tSendValue;
tSendValue.UWords[0] = aVendorCode;
@@ -154,7 +154,7 @@ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumb
tSendValue.UWords[1] = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble to parity
tSendValue.UBytes[4] = aCommand;
tSendValue.UBytes[5] = aCommand ^ tSendValue.UBytes[2] ^ tSendValue.UBytes[3]; // Parity
- sendPulseDistanceWidth(&KaseikyoProtocolConstants, tSendValue.ULongLong, KASEIKYO_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, tSendValue.ULongLong, KASEIKYO_BITS, aNumberOfRepeats);
#endif
}
@@ -208,18 +208,12 @@ bool IRrecv::decodeKaseikyo() {
return false;
}
- if (!checkHeader(&KaseikyoProtocolConstants)) {
+ if (!checkHeader_P(&KaseikyoProtocolConstants)) {
return false;
}
// decode first 16 Vendor ID bits
- if (!decodePulseDistanceWidthData(&KaseikyoProtocolConstants, KASEIKYO_VENDOR_ID_BITS)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Kaseikyo: "));
- Serial.println(F("Vendor ID decode failed"));
-#endif
- return false;
- }
+ decodePulseDistanceWidthData_P(&KaseikyoProtocolConstants, KASEIKYO_VENDOR_ID_BITS);
uint16_t tVendorId = decodedIRData.decodedRawData;
if (tVendorId == PANASONIC_VENDOR_ID_CODE) {
@@ -243,15 +237,9 @@ bool IRrecv::decodeKaseikyo() {
/*
* Decode next 32 bits, 8 VendorID parity parity + 12 address (device and subdevice) + 8 command + 8 parity
*/
- if (!decodePulseDistanceWidthData(&KaseikyoProtocolConstants,
+ decodePulseDistanceWidthData_P(&KaseikyoProtocolConstants,
KASEIKYO_VENDOR_ID_PARITY_BITS + KASEIKYO_ADDRESS_BITS + KASEIKYO_COMMAND_BITS + KASEIKYO_PARITY_BITS,
- 3 + (2 * KASEIKYO_VENDOR_ID_BITS))) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("Kaseikyo: "));
- Serial.println(F("VendorID parity, address, command + parity decode failed"));
-#endif
- return false;
- }
+ 3 + (2 * KASEIKYO_VENDOR_ID_BITS));
// Success
// decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value
diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp
index 52df1dbd0..28c04c654 100644
--- a/src/ir_LG.hpp
+++ b/src/ir_LG.hpp
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2017-2024 Darryl Smith, Armin Joachimsmeyer
+ * Copyright (c) 2017-2025 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
@@ -32,7 +32,7 @@
#ifndef _IR_LG_HPP
#define _IR_LG_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -114,11 +114,11 @@
//#define LG_REPEAT_DURATION (LG_HEADER_MARK + LG_REPEAT_HEADER_SPACE + LG_BIT_MARK)
//#define LG_REPEAT_DISTANCE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms
-struct PulseDistanceWidthProtocolConstants LGProtocolConstants = { LG, LG_KHZ, LG_HEADER_MARK, LG_HEADER_SPACE, LG_BIT_MARK,
-LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendNECSpecialRepeat };
+struct PulseDistanceWidthProtocolConstants const LGProtocolConstants PROGMEM= {LG, LG_KHZ, LG_HEADER_MARK, LG_HEADER_SPACE, LG_BIT_MARK,
+ LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendNECSpecialRepeat};
-struct PulseDistanceWidthProtocolConstants LG2ProtocolConstants = { LG2, LG_KHZ, LG2_HEADER_MARK, LG2_HEADER_SPACE, LG_BIT_MARK,
-LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendLG2SpecialRepeat };
+struct PulseDistanceWidthProtocolConstants const LG2ProtocolConstants PROGMEM = {LG2, LG_KHZ, LG2_HEADER_MARK, LG2_HEADER_SPACE, LG_BIT_MARK,
+ LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendLG2SpecialRepeat};
/************************************
* Start of send and decode functions
@@ -163,14 +163,14 @@ uint32_t IRsend::computeLGRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand
* LG uses the NEC repeat.
*/
void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
- sendPulseDistanceWidth(&LGProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidth_P(&LGProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats);
}
/**
* LG2 uses a special repeat.
*/
void IRsend::sendLG2(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) {
- sendPulseDistanceWidth(&LG2ProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidth_P(&LG2ProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats);
}
bool IRrecv::decodeLG() {
@@ -185,6 +185,7 @@ 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.rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawlen != 4)) {
+ // Is only printed, if LOCAL_DEBUG is defined globally
IR_DEBUG_PRINT(F("LG: "));
IR_DEBUG_PRINT(F("Data length="));
IR_DEBUG_PRINT(decodedIRData.rawlen);
@@ -193,8 +194,8 @@ bool IRrecv::decodeLG() {
}
// 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(irparams.rawbuf[1], LG_HEADER_MARK)) {
+ if (matchMark(irparams.rawbuf[1], LG2_HEADER_MARK)) {
tProtocol = LG2;
tHeaderSpace = LG2_HEADER_SPACE;
} else {
@@ -208,8 +209,7 @@ bool IRrecv::decodeLG() {
// Check for repeat - here we have another header space length
if (decodedIRData.rawlen == 4) {
- if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE)
- && matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) {
+ if (matchSpace(irparams.rawbuf[2], LG_REPEAT_HEADER_SPACE) && matchMark(irparams.rawbuf[3], LG_BIT_MARK)) {
decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST;
decodedIRData.address = lastDecodedAddress;
decodedIRData.command = lastDecodedCommand;
@@ -224,7 +224,7 @@ bool IRrecv::decodeLG() {
}
// Check command header space
- if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], tHeaderSpace)) {
+ if (!matchSpace(irparams.rawbuf[2], tHeaderSpace)) {
#if defined(LOCAL_DEBUG)
Serial.print(F("LG: "));
Serial.println(F("Header space length is wrong"));
@@ -232,13 +232,7 @@ bool IRrecv::decodeLG() {
return false;
}
- if (!decodePulseDistanceWidthData(&LGProtocolConstants, LG_BITS)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("LG: "));
- Serial.println(F("Decode failed"));
-#endif
- return false;
- }
+ decodePulseDistanceWidthData_P(&LGProtocolConstants, LG_BITS);
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
@@ -284,7 +278,7 @@ bool IRrecv::decodeLG() {
* @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent.
*/
void IRsend::sendLGRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats) {
- sendPulseDistanceWidth(&LGProtocolConstants, aRawData, LG_BITS, aNumberOfRepeats);
+ sendPulseDistanceWidth_P(&LGProtocolConstants, aRawData, LG_BITS, aNumberOfRepeats);
}
bool IRrecv::decodeLGMSB(decode_results *aResults) {
@@ -306,9 +300,8 @@ bool IRrecv::decodeLGMSB(decode_results *aResults) {
}
offset++;
- if (!decodePulseDistanceWidthData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) {
- return false;
- }
+ decodePulseDistanceWidthData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST);
+
// Stop bit
if (!matchMark(aResults->rawbuf[offset + (2 * LG_BITS)], LG_BIT_MARK)) {
#if defined(LOCAL_DEBUG)
diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp
index fed25bccf..1104395da 100644
--- a/src/ir_Lego.hpp
+++ b/src/ir_Lego.hpp
@@ -32,6 +32,12 @@
#ifndef _IR_LEGO_HPP
#define _IR_LEGO_HPP
+#if defined(DEBUG)
+#define LOCAL_DEBUG
+#else
+//#define LOCAL_DEBUG // This enables debug output only for this file
+#endif
+
/** \addtogroup Decoder Decoders and encoders for different protocols
* @{
*/
@@ -48,18 +54,30 @@
// 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 range 316 - 526 us
-// High bit range 526 � 947 us
-// Start/stop bit range 947 � 1579 us
+// Low bit consists of 6 cycles of IR and 10 cycles of pause,
+// High bit of 6 cycles IR and 21 cycles of pause,
+// Start/stop of 6 cycles IR and 39 cycles of pause.
+//
// If tm is the maximum message length (16ms) and Ch is the channel number, then
-// The delay before transmitting the first message is: (4 � Ch)*tm
-// The time from start to start for the next 2 messages is: 5*tm
-// The time from start to start for the following messages is: (6 + 2*Ch)*tm
+// The delay before transmitting the first message is: (4 - Ch) * tm
+// The time from start to start for the next 2 messages is: 5 * tm
+// The time from start to start for the following messages is: (6 + 2 * Ch) * tm
// Supported Devices
// LEGO Power Functions IR Receiver 8884
// MSB first, 1 start bit + 4 bit channel, 4 bit mode + 4 bit command + 4 bit parity + 1 stop bit.
+/* Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169 ,16 bits, MSB first, Gap=1050600us, Duration=10000us
+ Send with: IrSender.sendLego(0x1, 0x16, );
+ rawData[36]:
+ -1050600
+ + 250,- 950
+ + 250,- 500 + 200,- 200 + 200,- 250 + 200,- 500
+ + 200,- 250 + 200,- 500 + 200,- 500 + 200,- 250
+ + 200,- 500 + 200,- 200 + 250,- 200 + 200,- 200
+ + 250,- 500 + 200,- 200 + 250,- 200 + 200,- 250
+ + 200
+ Duration=10000us
+ */
+
#define LEGO_CHANNEL_BITS 4
#define LEGO_MODE_BITS 4
#define LEGO_COMMAND_BITS 4
@@ -73,6 +91,7 @@
#define LEGO_BIT_MARK 158 // 6 cycles
#define LEGO_ONE_SPACE 553 // 21 cycles
#define LEGO_ZERO_SPACE 263 // 10 cycles
+#define LEGO_ONE_THRESHOLD 408 // 15.5 cycles - not used, just for info
#define LEGO_AVERAGE_DURATION 11000 // LEGO_HEADER_MARK + LEGO_HEADER_SPACE + 16 * 600 + 158
@@ -83,9 +102,10 @@
#define LEGO_MODE_COMBO 1
#define LEGO_MODE_SINGLE 0x4 // here the 2 LSB have meanings like Output A / Output B
-struct PulseDistanceWidthProtocolConstants LegoProtocolConstants = { LEGO_PF, 38, LEGO_HEADER_MARK, LEGO_HEADER_SPACE, LEGO_BIT_MARK,
-LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (LEGO_AUTO_REPEAT_PERIOD_MIN
- / MICROS_IN_ONE_MILLI), NULL };
+// Cannot be constant, since we need to change RepeatPeriodMillis during sending
+struct PulseDistanceWidthProtocolConstants LegoProtocolConstants = { LEGO_PF, 38, LEGO_HEADER_MARK, LEGO_HEADER_SPACE,
+LEGO_BIT_MARK, LEGO_ONE_SPACE, LEGO_BIT_MARK, LEGO_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE,
+ (LEGO_AUTO_REPEAT_PERIOD_MIN / MICROS_IN_ONE_MILLI), nullptr };
/************************************
* Start of send and decode functions
@@ -107,8 +127,10 @@ void IRsend::sendLegoPowerFunctions(uint8_t aChannel, uint8_t aCommand, uint8_t
void IRsend::sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times) {
- IR_DEBUG_PRINT(F("sendLego aRawData=0x"));
- IR_DEBUG_PRINTLN(aRawData, HEX);
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("sendLego aRawData=0x"));
+ Serial.println(aRawData, HEX);
+#endif
aChannel &= 0x03; // we have 4 channels
@@ -127,31 +149,33 @@ void IRsend::sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aD
*/
bool IRrecv::decodeLegoPowerFunctions() {
- if (!checkHeader(&LegoProtocolConstants)) {
+ /*
+ * Check header timings
+ * Since LEGO_HEADER_MARK is just 158 us use a relaxed threshold compare (237) for it instead of matchMark()
+ */
+ if ((irparams.rawbuf[1] > LEGO_HEADER_MARK + (LEGO_HEADER_MARK / 2)) || (!matchSpace(irparams.rawbuf[2], LEGO_HEADER_SPACE))) {
return false;
}
// Check we have enough data - +4 for initial gap, start bit mark and space + stop bit mark
- if (decodedIRData.rawDataPtr->rawlen != (2 * LEGO_BITS) + 4) {
+ if (decodedIRData.rawlen != (2 * LEGO_BITS) + 4) {
IR_DEBUG_PRINT(F("LEGO: "));
IR_DEBUG_PRINT(F("Data length="));
- IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen);
+ IR_DEBUG_PRINT(irparams.rawlen);
IR_DEBUG_PRINTLN(F(" is not 36"));
return false;
}
- if (!decodePulseDistanceWidthData(&LegoProtocolConstants, LEGO_BITS)) {
- IR_DEBUG_PRINT(F("LEGO: "));
- IR_DEBUG_PRINTLN(F("Decode failed"));
- return false;
- }
+ decodePulseDistanceWidthData(&LegoProtocolConstants, LEGO_BITS);
- // Stop bit
- if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LEGO_BITS)], LEGO_BIT_MARK)) {
- IR_DEBUG_PRINT(F("LEGO: "));
- IR_DEBUG_PRINTLN(F("Stop bit mark length is wrong"));
- return false;
- }
+ // Stop bit, use threshold decoding - not required :-)
+// if (irparams.rawbuf[3 + (2 * LEGO_BITS)] > (2 * LEGO_BIT_MARK)) {
+//#if defined(LOCAL_DEBUG)
+// Serial.print(F("LEGO: "));
+// Serial.println(F("Stop bit mark length is wrong"));
+//#endif
+// return false;
+// }
// Success
decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST;
@@ -167,19 +191,21 @@ bool IRrecv::decodeLegoPowerFunctions() {
// parity check
if (tParityReceived != tParityComputed) {
- IR_DEBUG_PRINT(F("LEGO: "));
- IR_DEBUG_PRINT(F("Parity is not correct. expected=0x"));
- IR_DEBUG_PRINT(tParityComputed, HEX);
- IR_DEBUG_PRINT(F(" received=0x"));
- IR_DEBUG_PRINT(tParityReceived, HEX);
- IR_DEBUG_PRINT(F(", raw=0x"));
- IR_DEBUG_PRINT(tDecodedValue, HEX);
- IR_DEBUG_PRINT(F(", 3 nibbles are 0x"));
- IR_DEBUG_PRINT(tToggleEscapeChannel, HEX);
- IR_DEBUG_PRINT(F(", 0x"));
- IR_DEBUG_PRINT(tMode, HEX);
- IR_DEBUG_PRINT(F(", 0x"));
- IR_DEBUG_PRINTLN(tData, HEX);
+#if defined(LOCAL_DEBUG)
+ Serial.print(F("LEGO: "));
+ Serial.print(F("Parity is not correct. expected=0x"));
+ Serial.print(tParityComputed, HEX);
+ Serial.print(F(" received=0x"));
+ Serial.print(tParityReceived, HEX);
+ Serial.print(F(", raw=0x"));
+ Serial.print(tDecodedValue, HEX);
+ Serial.print(F(", 3 nibbles are 0x"));
+ Serial.print(tToggleEscapeChannel, HEX);
+ Serial.print(F(", 0x"));
+ Serial.print(tMode, HEX);
+ Serial.print(F(", 0x"));
+ Serial.println(tData, HEX);
+#endif
// might not be an error, so just continue
decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_MSB_FIRST;
}
@@ -191,7 +217,7 @@ bool IRrecv::decodeLegoPowerFunctions() {
decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT;
}
decodedIRData.address = tToggleEscapeChannel;
- decodedIRData.command = tData | tMode << LEGO_COMMAND_BITS;
+ decodedIRData.command = tData | (tMode << LEGO_COMMAND_BITS);
decodedIRData.numberOfBits = LEGO_BITS;
decodedIRData.protocol = LEGO_PF;
@@ -207,4 +233,7 @@ void IRsend::sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times) {
}
/** @}*/
+#if defined(LOCAL_DEBUG)
+#undef LOCAL_DEBUG
+#endif
#endif // _IR_LEGO_HPP
diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp
index 291f80869..3517fb694 100644
--- a/src/ir_MagiQuest.hpp
+++ b/src/ir_MagiQuest.hpp
@@ -14,7 +14,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2017-2024 E. Stuart Hicks , Armin Joachimsmeyer
+ * Copyright (c) 2017-2025 E. Stuart Hicks , 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
@@ -38,7 +38,7 @@
#ifndef _IR_MAGIQUEST_HPP
#define _IR_MAGIQUEST_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
@@ -55,7 +55,6 @@
//==============================================================================
/*
* https://github.com/kitlaan/Arduino-IRremote/blob/master/ir_Magiquest.cpp
- * https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1027#discussioncomment-3636857
* https://github.com/Arduino-IRremote/Arduino-IRremote/issues/1015#issuecomment-1222247231
Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first
@@ -94,6 +93,8 @@
#define MAGIQUEST_BITS (MAGIQUEST_CHECKSUM_BITS + MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) // 56 Size of the command with the start bits
/*
+ * Protocol is Pulse Distance Width not pure Pulse Distance and a longer space is not a one but a zero
+ *
* 0 = 25% mark & 75% space across 1 period
* 1150 * 0.25 = 288 usec mark
* 1150 - 288 = 862 usec space
@@ -108,10 +109,10 @@
#define MAGIQUEST_ZERO_MARK MAGIQUEST_UNIT // 287.5
#define MAGIQUEST_ZERO_SPACE (3 * MAGIQUEST_UNIT) // 864
-// assume 110 as repeat period
-struct PulseDistanceWidthProtocolConstants MagiQuestProtocolConstants = { MAGIQUEST, 38, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE,
-MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 110,
- NULL };
+// assume 110 as repeat period.
+struct PulseDistanceWidthProtocolConstants const MagiQuestProtocolConstants PROGMEM = {MAGIQUEST, 38, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE,
+ MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE,
+ PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE_WIDTH | SUPPRESS_STOP_BIT, 110, nullptr};
//+=============================================================================
//
/**
@@ -131,11 +132,11 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) {
tChecksum = ~tChecksum + 1;
// 8 start bits
- sendPulseDistanceWidthData(&MagiQuestProtocolConstants, 0, 8);
+ sendPulseDistanceWidthData_P(&MagiQuestProtocolConstants, 0, 8);
// 48 bit data
- sendPulseDistanceWidthData(&MagiQuestProtocolConstants, aWandId, MAGIQUEST_WAND_ID_BITS); // send only 31 bit, do not send MSB here
- sendPulseDistanceWidthData(&MagiQuestProtocolConstants, aMagnitude, MAGIQUEST_MAGNITUDE_BITS);
- sendPulseDistanceWidthData(&MagiQuestProtocolConstants, tChecksum, MAGIQUEST_CHECKSUM_BITS);
+ sendPulseDistanceWidthData_P(&MagiQuestProtocolConstants, aWandId, MAGIQUEST_WAND_ID_BITS); // send only 31 bit, do not send MSB here
+ sendPulseDistanceWidthData_P(&MagiQuestProtocolConstants, aMagnitude, MAGIQUEST_MAGNITUDE_BITS);
+ sendPulseDistanceWidthData_P(&MagiQuestProtocolConstants, tChecksum, MAGIQUEST_CHECKSUM_BITS);
#if defined(LOCAL_DEBUG)
// must be after sending, in order not to destroy the send timing
Serial.print(F("MagiQuest checksum=0x"));
@@ -165,14 +166,13 @@ bool IRrecv::decodeMagiQuest() {
/*
* Check for 8 zero header bits
*/
- if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_START_BITS, 1)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("MagiQuest: "));
- Serial.println(F("Start bit decode failed"));
+ decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_START_BITS, 1);
+#if defined(USE_THRESHOLD_DECODER)
+ if (decodedIRData.decodedRawData != 0xFF) // For Magiquest a small pause is a 1 which is inverse to threshold decoding
+#else
+ if (decodedIRData.decodedRawData != 0)
#endif
- return false;
- }
- if (decodedIRData.decodedRawData != 0) {
+ {
#if defined(LOCAL_DEBUG)
Serial.print(F("MagiQuest: "));
Serial.print(F("Not 8 leading zero start bits received, RawData=0x"));
@@ -184,18 +184,12 @@ bool IRrecv::decodeMagiQuest() {
/*
* Decode the 31 bit ID
*/
- if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_WAND_ID_BITS, (MAGIQUEST_START_BITS * 2) + 1)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("MagiQuest: "));
- Serial.println(F("ID decode failed"));
+ decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_WAND_ID_BITS, (MAGIQUEST_START_BITS * 2) + 1);
+#if defined(USE_THRESHOLD_DECODER)
+ decodedIRData.decodedRawData = decodedIRData.decodedRawData ^ 0x7FFFFFFF; // We have 31 bit. For Magiquest a small pause is a 1 which is inverse to threshold decoding
#endif
- return false;
- }
+
LongUnion tDecodedRawData;
-#if defined(LOCAL_DEBUG)
- Serial.print(F("31 bit WandId=0x"));
- Serial.println(decodedIRData.decodedRawData, HEX);
-#endif
uint32_t tWandId = decodedIRData.decodedRawData; // save tWandId for later use
tDecodedRawData.ULong = decodedIRData.decodedRawData << 1; // shift for checksum computation
uint8_t tChecksum = tDecodedRawData.Bytes[0] + tDecodedRawData.Bytes[1] + tDecodedRawData.Bytes[2] + tDecodedRawData.Bytes[3];
@@ -208,14 +202,13 @@ bool IRrecv::decodeMagiQuest() {
/*
* Decode the 9 bit Magnitude + 8 bit checksum
*/
- if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_CHECKSUM_BITS,
- ((MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) * 2) + 1)) {
-#if defined(LOCAL_DEBUG)
- Serial.print(F("MagiQuest: "));
- Serial.println(F("Magnitude + checksum decode failed"));
+ decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_CHECKSUM_BITS,
+ ((MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) * 2) + 1);
+
+#if defined(USE_THRESHOLD_DECODER)
+ decodedIRData.decodedRawData = decodedIRData.decodedRawData ^ 0x0001FFFF; // We have 17 bit. For Magiquest a small pause is a 1 which is inverse to threshold decoding
+
#endif
- return false;
- }
#if defined(LOCAL_DEBUG)
Serial.print(F("Magnitude + checksum=0x"));
diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp
index b02931cc7..e70c87c88 100644
--- a/src/ir_NEC.hpp
+++ b/src/ir_NEC.hpp
@@ -8,7 +8,7 @@
************************************************************************************
* MIT License
*
- * Copyright (c) 2020-2023 Armin Joachimsmeyer
+ * Copyright (c) 2020-2025 Armin Joachimsmeyer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@
#ifndef _IR_NEC_HPP
#define _IR_NEC_HPP
-#if defined(DEBUG) && !defined(LOCAL_DEBUG)
+#if defined(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. IR_DEBUG_PRINT is still a void function here.
@@ -72,7 +72,7 @@
// http://www.hifi-remote.com/wiki/index.php/NEC
// https://www.sbprojects.net/knowledge/ir/nec.php
// NEC: LSB first, (or ) .
-// ONKYO: like NEC but force to 16 independent address and 16 bit command bits: