From b9e2157d2753ac6f6a8badf28703b916631e5d3e Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 25 Jul 2023 11:05:59 +0200 Subject: [PATCH 001/133] Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense --- changelog.md | 1 + src/private/IRTimer.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 748f7e2bf..3327b628a 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Enable Bang&Olufsen 455 kHz if SEND_PWM_BY_TIMER is defined. - Fixed bug: TinyReceiver throwing ISR not in IRAM on ESP8266. - Usage of ATTinyCore pin numbering scheme e.g. PIN_PB2. +- Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense. ## 4.1.2 - Workaround for ESP32 RTOS delay() timing bug influencing the mark() function. diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 1d87c971e..6dee61bde 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1695,7 +1695,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { /*************************************** * NRF5 boards like the BBC:Micro ***************************************/ -#elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) +#elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840) || defined(ARDUINO_ARCH_NRF52) # if defined(SEND_PWM_BY_TIMER) #error PWM generation by hardware not implemented for NRF5 # endif From f9cf150cd96d21bf625d0d8fa80f4eef036ea720 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 26 Jul 2023 22:15:40 +0200 Subject: [PATCH 002/133] First UNO R4 support --- .github/workflows/LibraryBuild.yml | 6 ++ .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 9 +++ examples/ControlRelay/PinDefinitionsAndMore.h | 9 +++ .../IRDispatcherDemo/PinDefinitionsAndMore.h | 9 +++ .../PinDefinitionsAndMore.h | 9 +++ examples/MicroGirs/PinDefinitionsAndMore.h | 9 +++ .../ReceiveAndSend/PinDefinitionsAndMore.h | 9 +++ .../PinDefinitionsAndMore.h | 9 +++ examples/ReceiveDemo/PinDefinitionsAndMore.h | 9 +++ examples/ReceiveDump/PinDefinitionsAndMore.h | 9 +++ .../PinDefinitionsAndMore.h | 9 +++ .../SendAndReceive/PinDefinitionsAndMore.h | 9 +++ .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 9 +++ examples/SendDemo/PinDefinitionsAndMore.h | 9 +++ .../PinDefinitionsAndMore.h | 9 +++ .../SendProntoDemo/PinDefinitionsAndMore.h | 9 +++ examples/SendRawDemo/PinDefinitionsAndMore.h | 9 +++ .../SimpleReceiver/PinDefinitionsAndMore.h | 9 +++ .../PinDefinitionsAndMore.h | 9 +++ examples/SimpleSender/PinDefinitionsAndMore.h | 9 +++ examples/UnitTest/PinDefinitionsAndMore.h | 9 +++ library.properties | 2 +- src/private/IRTimer.hpp | 63 +++++++++++++++++++ 23 files changed, 250 insertions(+), 1 deletion(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 444d3bde9..01ddcbe41 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -55,6 +55,7 @@ jobs: - 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 - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico @@ -138,6 +139,11 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 + - 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=700 + - 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 diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index ce84aa482..d794db4a8 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -153,6 +153,15 @@ # endif # endif // defined(__AVR_ATtiny25__)... +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 +// To be compatible with UNO R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 diff --git a/library.properties b/library.properties index ad2bdd36b..4ecf3bae9 100644 --- a/library.properties +++ b/library.properties @@ -6,5 +6,5 @@ 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.

New: Added FAST Protocol. Changed some function signatures. Improved handling of PULSE_DISTANCE + PULSE_WIDTH protocols.
Release notes
category=Communication url=https://github.com/Arduino-IRremote/Arduino-IRremote -architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040 +architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno includes=IRremote.hpp diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 6dee61bde..b28033210 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -85,6 +85,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz); //#define __STM32F1__ //#define STM32F1xx //#define PARTICLE +//#define ARDUINO_ARCH_RENESAS #if defined (DOXYGEN) /** @@ -1084,6 +1085,68 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { * End of AVR timers **********************************************************************************************************************/ +/********************************************** + * UNO R4 boards + * The FspTimer uses undocumented + **********************************************/ +#elif defined(ARDUINO_ARCH_RENESAS) +#include "FspTimer.h" +FspTimer s50usTimer; + +// Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler() +# if defined(ISR) +#undef ISR +# endif + +// callback method used by timer +void IRTimerInterruptHandlerHelper(timer_callback_args_t __attribute((unused)) *p_args) { + IRReceiveTimerInterruptHandler(); +} +void timerEnableReceiveInterrupt() { +// s50usTimer.enable_overflow_irq(); + s50usTimer.start(); +} +void timerDisableReceiveInterrupt() { +// s50usTimer.disable_overflow_irq(); + s50usTimer.stop(); // May save power +} + +void timerConfigForReceive() { + uint8_t tTimerType = GPT_TIMER; + int8_t tIndex = FspTimer::get_available_timer(tTimerType); // Get first unused channel. Here we need the address of tTimerType + if (tIndex < 0 || tTimerType != GPT_TIMER) { + // here we found no unused GPT channel + tIndex = FspTimer::get_available_timer(tTimerType, true); // true to force use of already used PWM channel. Sets "force_pwm_reserved" if timer found + if (tIndex < 0) { + // If we already get an tIndex < 0 we have an error, but do not know how to handle :-( + return; + } + } + s50usTimer.begin(TIMER_MODE_PERIODIC, tTimerType, tIndex, MICROS_IN_ONE_SECOND / MICROS_PER_TICK, 0.0, + IRTimerInterruptHandlerHelper); + s50usTimer.setup_overflow_irq(); + s50usTimer.open(); // In turn calls R_GPT_Enable() + s50usTimer.stop(); // May save power +} + +# if defined(SEND_PWM_BY_TIMER) +#error PWM generation by hardware not yet implemented for Arduino Uno R4 +// Not yet implemented +void enableSendPWMByTimer() { +} +void disableSendPWMByTimer() { +} + +/* + * timerConfigForSend() is used exclusively by IRsend::enableIROut() + */ +void timerConfigForSend(uint16_t aFrequencyKHz) { +# if defined(IR_SEND_PIN) +# else +# endif +} +# endif + /********************************************** * Teensy 3.0 / Teensy 3.1 / Teensy 3.2 boards **********************************************/ From c2a3858a26635313a3d553fdac42fd1a31e9e037 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 1 Aug 2023 19:56:34 +0200 Subject: [PATCH 003/133] Fixes #1152 --- src/IRSend.hpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 195a47fa1..708814698 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -933,6 +933,8 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas * The mark output is modulated at the PWM frequency if USE_NO_SEND_PWM is not defined. * The output is guaranteed to be OFF / inactive after after the call of the function. * This function may affect the state of feedback LED. + * Period time is 26 us for 38.46 kHz, 27 us for 37.04 kHz, 25 us for 40 kHz. + * On time is 8 us for 30% duty cycle */ void IRsend::mark(uint16_t aMarkMicros) { @@ -1000,7 +1002,7 @@ void IRsend::mark(uint16_t aMarkMicros) { // 4.3 us from do{ to pin setting if sendPin is no constant digitalWriteFast(sendPin, HIGH); # endif - delayMicroseconds (periodOnTimeMicros); // this is normally implemented by a blocking wait + delayMicroseconds(periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait. /* * Output the PWM pause @@ -1034,12 +1036,15 @@ void IRsend::mark(uint16_t aMarkMicros) { # endif /* * PWM pause timing - * Measured delta between pause duration values are 13 us for a 16 MHz UNO (from 13 to 26) + * 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; - noInterrupts(); +#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 do { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles @@ -1051,19 +1056,19 @@ void IRsend::mark(uint16_t aMarkMicros) { * The rest of the loop takes 1.2 us with NO_LED_FEEDBACK_CODE enabled * and 3 us with NO_LED_FEEDBACK_CODE disabled. */ - tMicros = micros(); // #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 */ - unsigned int tDeltaMicros = tMicros - tStartMicros; + tMicros = micros(); + uint16_t tDeltaMicros = tMicros - tStartMicros; #if defined(__AVR__) -// tDeltaMicros += (160 / CLOCKS_PER_MICRO); // adding this once increases program size ! + // 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. - // reset feedback led in the last pause before end if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } @@ -1079,7 +1084,9 @@ void IRsend::mark(uint16_t aMarkMicros) { } # endif #endif +#if defined(__AVR__) interrupts(); +#endif return; } } while (tMicros < tNextPeriodEnding); From 6251c697fbae09a0bc5aca26a053078cfdf7bcf5 Mon Sep 17 00:00:00 2001 From: Armin Date: Sat, 5 Aug 2023 11:26:17 +0200 Subject: [PATCH 004/133] Fixes #1153 --- src/private/IRTimer.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index b28033210..731faf00f 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -458,7 +458,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { # endif // defined(SEND_PWM_BY_TIMER) /* - * AVR Timer2 (8 bits) // Tone timer on UNO + * AVR Timer2 (8 bits) // Tone timer on Uno */ #elif defined(IR_USE_AVR_TIMER2) @@ -1086,7 +1086,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { **********************************************************************************************************************/ /********************************************** - * UNO R4 boards + * Uno R4 boards * The FspTimer uses undocumented **********************************************/ #elif defined(ARDUINO_ARCH_RENESAS) From 8cedd6b2531d7b0216b7f482df05e5cbc30aa2b3 Mon Sep 17 00:00:00 2001 From: Armin Date: Sat, 5 Aug 2023 11:26:48 +0200 Subject: [PATCH 005/133] Documentation --- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 4 ++-- examples/ControlRelay/PinDefinitionsAndMore.h | 4 ++-- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 4 ++-- .../PinDefinitionsAndMore.h | 4 ++-- examples/MicroGirs/PinDefinitionsAndMore.h | 4 ++-- .../ReceiveAndSend/PinDefinitionsAndMore.h | 4 ++-- .../PinDefinitionsAndMore.h | 4 ++-- examples/ReceiveDemo/PinDefinitionsAndMore.h | 4 ++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 4 ++-- .../PinDefinitionsAndMore.h | 4 ++-- .../SendAndReceive/PinDefinitionsAndMore.h | 4 ++-- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 4 ++-- examples/SendDemo/PinDefinitionsAndMore.h | 4 ++-- .../PinDefinitionsAndMore.h | 4 ++-- .../SendProntoDemo/PinDefinitionsAndMore.h | 4 ++-- examples/SendRawDemo/PinDefinitionsAndMore.h | 4 ++-- .../SimpleReceiver/PinDefinitionsAndMore.h | 4 ++-- .../PinDefinitionsAndMore.h | 4 ++-- examples/SimpleSender/PinDefinitionsAndMore.h | 4 ++-- examples/UnitTest/PinDefinitionsAndMore.h | 4 ++-- src/IRReceive.hpp | 22 +++++++------------ src/digitalWriteFast.h | 2 ++ 22 files changed, 50 insertions(+), 54 deletions(-) diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index d794db4a8..aa85fdddf 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -153,8 +153,8 @@ # endif # endif // defined(__AVR_ATtiny25__)... -#elif defined(ARDUINO_ARCH_RENESAS_UNO) // UNO R4 -// To be compatible with UNO R3. +#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 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index a1bf0b488..ddbd6a231 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -124,7 +124,7 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif -void IRReceiveTimerInterruptHandler(){ +void IRReceiveTimerInterruptHandler() { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles #endif @@ -173,7 +173,7 @@ void IRReceiveTimerInterruptHandler(){ irparams.rawlen = 1; irparams.StateForISR = IR_REC_STATE_MARK; } // otherwise stay in idle state - irparams.TickCounterForISR = 0;// reset counter in both cases + irparams.TickCounterForISR = 0; // reset counter in both cases } } else if (irparams.StateForISR == IR_REC_STATE_MARK) { // Timing mark @@ -186,7 +186,7 @@ void IRReceiveTimerInterruptHandler(){ #endif irparams.rawbuf[irparams.rawlen++] = irparams.TickCounterForISR; // record mark irparams.StateForISR = IR_REC_STATE_SPACE; - irparams.TickCounterForISR = 0;// This resets the tick counter also at end of frame :-) + irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-) } } else if (irparams.StateForISR == IR_REC_STATE_SPACE) { // Timing space @@ -664,6 +664,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8 // get one mark and space pair unsigned int tMarkTicks; unsigned int tSpaceTicks; + bool tBitValue; if (isPulseDistanceProtocol) { /* @@ -676,6 +677,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8 tRawBufPointer++; #endif 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 #if defined DECODE_STRICT_CHECKS // Check for constant length mark @@ -698,6 +700,8 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8 * Pulse width here, it is not required to check (constant) space duration and zero mark duration. */ tMarkTicks = *tRawBufPointer++; + tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 + #if defined DECODE_STRICT_CHECKS tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) #else @@ -710,17 +714,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8 if (aMSBfirst) { tDecodedData <<= 1; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" - bool tBitValue; - if (isPulseDistanceProtocol) { - // Check for variable length space indicating a 1 or 0 - tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // tSpaceTicks is initialized here, even if some compiler are complaining! - } else { - // Check for variable length mark indicating a 1 or 0 - tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // tMarkTicks is initialized here, even if some compiler are complaining! - } -#pragma GCC diagnostic pop + if (tBitValue) { // It's a 1 -> set the bit if (aMSBfirst) { diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index 5da511107..1bb8eb507 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -27,6 +27,8 @@ # define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit)) #endif +#include // declarations for the fallback to digitalWrite(), digitalRead() etc. + // --- Arduino Mega and ATmega128x/256x based boards --- #if (defined(ARDUINO_AVR_MEGA) || \ defined(ARDUINO_AVR_MEGA1280) || \ From 5507618f93d8d406d63abf54b124c495187840b2 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 7 Aug 2023 21:45:57 +0200 Subject: [PATCH 006/133] Closes #1155 --- src/private/IRTimer.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 731faf00f..872b9fb0a 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -408,7 +408,8 @@ void disableSendPWMByTimer() { # else # if defined(USE_TIMER_CHANNEL_B) void enableSendPWMByTimer() { - TCNT1 = 0; (TCCR1A |= _BV(COM1B1)) // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting. + TCNT1 = 0; + TCCR1A |= _BV(COM1B1); // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when counting down. } void disableSendPWMByTimer() { TCCR1A &= ~(_BV(COM1B1)); @@ -694,8 +695,13 @@ void timerConfigForReceive() { # endif # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro -void enableSendPWMByTimer() { TCNT4 = 0; (TCCR4A |= _BV(COM4A0)) // Use complementary OC4A output on pin 5 -void disableSendPWMByTimer() { (TCCR4A &= ~(_BV(COM4A0))) // (Pro Micro does not map PC7 (32/ICP3/CLK0/OC4A) +void enableSendPWMByTimer() { + TCNT4 = 0; + TCCR4A |= _BV(COM4A0); // Use complementary OC4A output on pin 5 +} +void disableSendPWMByTimer() { + TCCR4A &= ~(_BV(COM4A0)); // (Pro Micro does not map PC7 (32/ICP3/CLK0/OC4A) +} // of ATmega32U4 ) # else void enableSendPWMByTimer() { From 36e4a19ff895614a20a8bb6b94e97d60e6589983 Mon Sep 17 00:00:00 2001 From: Armin Date: Sat, 12 Aug 2023 09:17:50 +0200 Subject: [PATCH 007/133] Documentation --- examples/AllProtocolsOnLCD/ADCUtils.h | 8 ++- examples/AllProtocolsOnLCD/ADCUtils.hpp | 67 ++++++++++++++----- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 +- examples/ReceiveDump/ReceiveDump.ino | 2 +- examples/UnitTest/UnitTest.ino | 2 +- src/IRReceive.hpp | 9 --- src/IRremote.h | 2 + 7 files changed, 62 insertions(+), 30 deletions(-) diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 5aaaaf718..cc7e629d0 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -115,8 +115,8 @@ extern float sVCCVoltage; extern uint16_t sVCCVoltageMillivolt; -extern long sLastVoltageCheckMillis; -extern uint8_t sVoltageTooLowCounter; +extern long sLastVCCCheckMillis; +extern uint8_t sVCCTooLowCounter; uint16_t readADCChannel(uint8_t aChannelNumber); uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference); @@ -157,7 +157,9 @@ float getTemperature(void); bool isVCCTooLowMultipleTimes(); void resetVCCTooLowMultipleTimes(); -bool isVoltageTooLow(); +bool isVCCTooLow(); +bool isVCCTooHigh(); +bool isVCCTooHighSimple(); #endif // defined(__AVR__) ... #endif // _ADC_UTILS_H diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 079d177da..752175c45 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -61,8 +61,8 @@ float sVCCVoltage; uint16_t sVCCVoltageMillivolt; // for isVCCTooLowMultipleTimes() -long sLastVoltageCheckMillis; -uint8_t sVoltageTooLowCounter = 0; +long sLastVCCCheckMillis; +uint8_t sVCCTooLowCounter = 0; /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. @@ -155,7 +155,7 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8 /* * Switch reference from DEFAULT to INTERNAL */ - delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for UNO board + delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board } else if ((tOldADMUX & 0x0F) != aChannelNumber) { if (aChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) { /* @@ -361,6 +361,10 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe * !!! Function without handling of switched reference and channel.!!! * Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program. * !!! Resolution is only 20 millivolt !!! + * Raw reading of 1.1 V is 225 at 5 V. + * Raw reading of 1.1 V is 221 at 5.1 V. + * Raw reading of 1.1 V is 214 at 5.25 V (+5 %). + * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). */ float getVCCVoltageSimple(void) { // use AVCC with (optional) external capacitor at AREF pin as reference @@ -384,7 +388,7 @@ uint16_t getVCCVoltageMillivoltSimple(void) { * Similar to getVCCVoltageMillivolt() * 1023 / 1100 */ uint16_t getVCCVoltageReadingFor1_1VoltReference(void) { - uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT); // 225 for 1.1 V at 5 V VCC + uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT); /* * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement */ @@ -402,6 +406,10 @@ float getVCCVoltage(void) { * Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference. * Handles reference and channel switching by introducing the appropriate delays. * !!! Resolution is only 20 millivolt !!! + * Raw reading of 1.1 V is 225 at 5 V. + * Raw reading of 1.1 V is 221 at 5.1 V. + * Raw reading of 1.1 V is 214 at 5.25 V (+5 %). + * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). */ uint16_t getVCCVoltageMillivolt(void) { uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT); @@ -502,6 +510,12 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM #if !defined(VCC_EMERGENCY_STOP_MILLIVOLT) #define VCC_EMERGENCY_STOP_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt #endif +#if !defined(VCC_TOO_HIGH_STOP_MILLIVOLT) +#define VCC_TOO_HIGH_STOP_MILLIVOLT 5250 // + 5 % operation voltage +#endif +#if !defined(VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT) +#define VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT 5500 // +10 %. Max recommended operation voltage +#endif #if !defined(VCC_CHECK_PERIOD_MILLIS) #define VCC_CHECK_PERIOD_MILLIS 10000 // Period of VCC checks #endif @@ -517,8 +531,8 @@ bool isVCCTooLowMultipleTimes() { * Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds */ - if (millis() - sLastVoltageCheckMillis >= VCC_CHECK_PERIOD_MILLIS) { - sLastVoltageCheckMillis = millis(); + if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) { + sLastVCCCheckMillis = millis(); # if defined(INFO) readAndPrintVCCVoltageMillivolt(&Serial); @@ -526,31 +540,31 @@ bool isVCCTooLowMultipleTimes() { readVCCVoltageMillivolt(); # endif - if (sVoltageTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) { + if (sVCCTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) { /* * Do not check again if shutdown has happened */ if (sVCCVoltageMillivolt > VCC_STOP_THRESHOLD_MILLIVOLT) { - sVoltageTooLowCounter = 0; // reset counter + sVCCTooLowCounter = 0; // reset counter } else { /* * Voltage too low, wait VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times and then shut down. */ if (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT) { // emergency shutdown - sVoltageTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP; + sVCCTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP; # if defined(INFO) Serial.println(F("Voltage < " STR(VCC_EMERGENCY_STOP_MILLIVOLT) " mV detected -> emergency shutdown")); # endif } else { - sVoltageTooLowCounter++; + sVCCTooLowCounter++; # if defined(INFO) Serial.print(F("Voltage < " STR(VCC_STOP_THRESHOLD_MILLIVOLT) " mV detected: ")); - Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVoltageTooLowCounter); + Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVCCTooLowCounter); Serial.println(F(" tries left")); # endif } - if (sVoltageTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) { + if (sVCCTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) { /* * 6 times voltage too low -> shutdown */ @@ -562,12 +576,35 @@ bool isVCCTooLowMultipleTimes() { return false; } + +/* + * Return true if VCC_EMERGENCY_STOP_MILLIVOLT (3 V) reached + */ +bool isVCCTooLow(){ + return (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT); +} + + void resetVCCTooLowMultipleTimes(){ - sVoltageTooLowCounter = 0; + sVCCTooLowCounter = 0; } -bool isVoltageTooLow(){ - return (sVoltageTooLowCounter >= VCC_CHECKS_TOO_LOW_BEFORE_STOP); +/* + * Recommended VCC is 1.8 V to 5.5 V, absolute maximum VCC is 6.0 V. + * Check for 5.25 V, because such overvoltage is quite unlikely to happen during regular operation. + * Raw reading of 1.1 V is 225 at 5 V. + * Raw reading of 1.1 V is 221 at 5.1 V. + * Raw reading of 1.1 V is 214 at 5.25 V (+5 %). + * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). + * @return true if 5 % overvoltage reached + */ +bool isVCCTooHigh(){ + readVCCVoltageMillivolt(); + return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); +} +bool isVCCTooHighSimple(){ + readVCCVoltageMillivoltSimple(); + return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); } /* diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index bc514a194..e26b64323 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -182,7 +182,7 @@ void setup() { #if defined(USE_SERIAL_LCD) myLCD.init(); myLCD.clear(); - myLCD.backlight(); + myLCD.backlight(); // Switch backlight LED on #endif #if defined(USE_PARALLEL_LCD) myLCD.begin(LCD_COLUMNS, LCD_ROWS); // This also clears display diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 0f3297788..23b9b5759 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -129,7 +129,7 @@ void loop() { * Example for using the compensateAndStorePronto() function. * Creating this String requires 2210 bytes program memory and 10 bytes RAM for the String class. * The String object itself requires additional 440 bytes RAM from the heap. - * This values are for an Arduino UNO. + * This values are for an Arduino Uno. */ // Serial.println(); // blank line between entries // String ProntoHEX = F("Pronto HEX contains: "); // Assign string to ProtoHex string object diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index b9a88d11b..dfae7cb5f 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -379,7 +379,7 @@ void loop() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. if (sAddress == 0xFFF1) { -# if FLASHEND >= 0x7FFF // For 32k flash or more, like UNO. Code does not fit in program memory of ATtiny1604 etc. +# if FLASHEND >= 0x7FFF // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc. /* * Send constant values only once in this demo */ diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index ddbd6a231..227a3ce57 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1651,20 +1651,11 @@ const char* IRrecv::getProtocolString() { * aResults->decode_type **********************************************************************************************************************/ bool IRrecv::decode_old(decode_results *aResults) { - static bool sDeprecationMessageSent = false; if (irparams.StateForISR != IR_REC_STATE_STOP) { return false; } - if (!sDeprecationMessageSent) { -#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) -// Serial.println( -// "The function decode(&results)) is deprecated and may not work as expected! Just use decode() without a parameter and IrReceiver.decodedIRData. ."); -#endif - sDeprecationMessageSent = true; - } - // copy for usage by legacy programs aResults->rawbuf = irparams.rawbuf; aResults->rawlen = irparams.rawlen; diff --git a/src/IRremote.h b/src/IRremote.h index 9b2ab8ccf..90a91e4d1 100644 --- a/src/IRremote.h +++ b/src/IRremote.h @@ -33,6 +33,8 @@ bool IRrecv::decode(decode_results *aResults) { 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(); + Serial.println(F("Thanks")); Serial.println(F("**************************************************************************************************")); Serial.println(); Serial.println(); From 3a443bbac096df9fa2ef0ecbfc47166fc256591d Mon Sep 17 00:00:00 2001 From: Armin Date: Sat, 12 Aug 2023 09:48:16 +0200 Subject: [PATCH 008/133] Bumped version to 4.2.0. Extraced version macros to IRVersion.h. --- changelog.md | 2 ++ library.json | 2 +- library.properties | 4 ++-- src/IRVersion.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++ src/IRremote.hpp | 12 +---------- 5 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/IRVersion.h diff --git a/changelog.md b/changelog.md index 3327b628a..c1bbb52bf 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Fixed bug: TinyReceiver throwing ISR not in IRAM on ESP8266. - Usage of ATTinyCore pin numbering scheme e.g. PIN_PB2. - Added ARDUINO_ARCH_NRF52 to support Seeed XIAO nRF52840 Sense. +- First untested support of Uno R4. +- Extraced version macros to IRVersion.h. ## 4.1.2 - Workaround for ESP32 RTOS delay() timing bug influencing the mark() function. diff --git a/library.json b/library.json index 9bfa9873f..e264f4c88 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/z3t0/Arduino-IRremote.git" }, - "version": "4.1.2", + "version": "4.2.0", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index 4ecf3bae9..75ad868d0 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.1.2 +version=4.2.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.

New: Added FAST Protocol. Changed some function signatures. Improved handling of PULSE_DISTANCE + PULSE_WIDTH protocols.
Release notes
+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.

New: Added untested Uno R4 support. Improved ESP support. Added DECODE_ONKYO. Old decode() prints a message now.
Release notes
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/src/IRVersion.h b/src/IRVersion.h new file mode 100644 index 000000000..06cd4d40c --- /dev/null +++ b/src/IRVersion.h @@ -0,0 +1,51 @@ +/** + * @file IRversion.hpp + * + * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * + ************************************************************************************ + * MIT License + * + * Copyright (c) 2015-2023 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************************ + * + * For Ken Shiriffs original blog entry, see http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html + * Initially influenced by: + * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556 + * and http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/ + */ + +#ifndef _IR_VERSION_HPP +#define _IR_VERSION_HPP + +#define VERSION_IRREMOTE "4.2.0" +#define VERSION_IRREMOTE_MAJOR 4 +#define VERSION_IRREMOTE_MINOR 2 +#define VERSION_IRREMOTE_PATCH 0 + +/* + * Macro to convert 3 version parts into an integer + * To be used in preprocessor comparisons, such as #if VERSION_IRREMOTE_HEX >= VERSION_HEX_VALUE(3, 7, 0) + */ +#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) +#define VERSION_IRREMOTE_HEX VERSION_HEX_VALUE(VERSION_IRREMOTE_MAJOR, VERSION_IRREMOTE_MINOR, VERSION_IRREMOTE_PATCH) + +#endif // _IR_VERSION_HPP diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 7baa0bf78..f3e2919da 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -65,17 +65,7 @@ #ifndef _IR_REMOTE_HPP #define _IR_REMOTE_HPP -#define VERSION_IRREMOTE "4.1.0" -#define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 1 -#define VERSION_IRREMOTE_PATCH 0 - -/* - * Macro to convert 3 version parts into an integer - * To be used in preprocessor comparisons, such as #if VERSION_IRREMOTE_HEX >= VERSION_HEX_VALUE(3, 7, 0) - */ -#define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) -#define VERSION_IRREMOTE_HEX VERSION_HEX_VALUE(VERSION_IRREMOTE_MAJOR, VERSION_IRREMOTE_MINOR, VERSION_IRREMOTE_PATCH) +#include "IRVersion.h" // 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 From fe2010270eeb7dcea084aaedf9da981070ce6f2d Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 14 Aug 2023 17:46:21 +0200 Subject: [PATCH 009/133] Documentation inspired by #1158 --- README.md | 1 + examples/SendDemo/SendDemo.ino | 1 + examples/UnitTest/UnitTest.ino | 1 + src/ir_JVC.hpp | 1 + src/ir_NEC.hpp | 1 + 5 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 5d186af5f..8bf029613 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,7 @@ Example: `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.
diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 97e7fa29a..e6bd7d0cf 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -165,6 +165,7 @@ void loop() { /* * With Send sendNECMSB() you can send your old 32 bit codes. * To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte. + * Use bitreverse32Bit(). * Example: * 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3 */ diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index dfae7cb5f..de76e93c3 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -419,6 +419,7 @@ void loop() { /* * With Send sendNECMSB() you can send your old 32 bit codes. * To convert one into the other, you must reverse the byte positions and then reverse all positions of each byte. + * Use bitreverse32Bit(). * Example: * 0xCB340102 byte reverse -> 0x020134CB bit reverse-> 40802CD3 */ diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 89f9f919f..24ef4fb47 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -231,6 +231,7 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) { /** * With Send sendJVCMSB() you can send your old 32 bit codes. * To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte. + * Use bitreverse32Bit(). * Or write it as one binary string and reverse/mirror it. * Example: * 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3. diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 1c02e7d4f..b68942537 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -401,6 +401,7 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) { /** * With Send sendNECMSB() you can send your old 32 bit codes. * To convert one into the other, you must reverse the byte positions and then reverse all bit positions of each byte. + * Use bitreverse32Bit(). * Or write it as one binary string and reverse/mirror it. * Example: * 0xCB340102 byte reverse -> 02 01 34 CB bit reverse-> 40 80 2C D3. From 480ca42b1aa925806c838a2cbeae79aa07503333 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 15 Aug 2023 10:21:45 +0200 Subject: [PATCH 010/133] Documentation --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- .github/workflows/LibraryBuild.yml | 42 ++--- README.md | 1 + examples/AllProtocolsOnLCD/ADCUtils.h | 35 ++-- examples/AllProtocolsOnLCD/ADCUtils.hpp | 173 ++++++++++++------ .../IRremoteExtensionClass.cpp | 5 + .../IRremoteExtensionClass.h | 1 + src/IRremote.h | 1 + src/private/IRTimer.hpp | 1 - 9 files changed, 162 insertions(+), 99 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 662af9989..95c4245c1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -18,7 +18,7 @@ body: attributes: label: The type of board you are using. options: - - Arduino ATmega328* board (UNO, Nano, etc.) + - Arduino ATmega328* board (Uno, Nano, etc.) - Arduino ATmega2560 board (Mega) - Arduino ATmega32U4 board (Leonardo, etc.) - Arduino ATmega4809 megaAVR board (NanoEvery) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 01ddcbe41..2f2106972 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -60,9 +60,9 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect - - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro # - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 @@ -183,26 +183,26 @@ jobs: # build-properties: # the flags were put in compiler.cpp.extra_flags # IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 - - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - arduino-boards-fqbn: MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json diff --git a/README.md b/README.md index 8bf029613..1e35cc3d8 100644 --- a/README.md +++ b/README.md @@ -725,6 +725,7 @@ If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easi
ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board. - Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc. +- Arduino Uno R4, but not yet tested, because of lack of a R4 board. - Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 3.2 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team) - Sanguino - ATmega8, 48, 88, 168, 328 diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index cc7e629d0..1abe62a51 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -118,21 +118,21 @@ extern uint16_t sVCCVoltageMillivolt; extern long sLastVCCCheckMillis; extern uint8_t sVCCTooLowCounter; -uint16_t readADCChannel(uint8_t aChannelNumber); -uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference); -uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference); -uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aChannelNumber, uint8_t aReference); -uint16_t readADCChannelWithOversample(uint8_t aChannelNumber, uint8_t aOversampleExponent); -void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference); -uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); -uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); -uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); -uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples); -uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire); -uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference, - uint8_t aMaxRetries); - -uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference); +uint16_t readADCChannel(uint8_t aADCChannelNumber); +uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); +uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); +uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference); +uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent); +void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference); +uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); +uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); +uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); +uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples); +uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire); +uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay, + uint8_t aAllowedDifference, uint8_t aMaxRetries); + +uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference); /* * readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage @@ -152,8 +152,9 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial); uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement); uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement); uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement); -float getTemperatureSimple(void); -float getTemperature(void); +float getCPUTemperatureSimple(void); +float getCPUTemperature(void); +float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated bool isVCCTooLowMultipleTimes(); void resetVCCTooLowMultipleTimes(); diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 752175c45..6d78bdd8f 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -3,7 +3,7 @@ * * ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h. * - * Copyright (C) 2016-2022 Armin Joachimsmeyer + * Copyright (C) 2016-2023 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. @@ -26,7 +26,7 @@ #define _ADC_UTILS_HPP #include "ADCUtils.h" -#if defined(ADC_UTILS_ARE_AVAILABLE) +#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected #if !defined(STR_HELPER) #define STR_HELPER(x) #x @@ -54,6 +54,16 @@ union WordUnionForADCUtils { uint8_t *BytePointer; }; +/* + * Enable this to see information on each call. + * Since there should be no library which uses Serial, it should only be enabled for development purposes. + */ +#if defined(DEBUG) +#define LOCAL_DEBUG +#else +//#define LOCAL_DEBUG // This enables debug output only for this file +#endif + /* * Persistent storage for VCC value */ @@ -67,9 +77,9 @@ uint8_t sVCCTooLowCounter = 0; /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. */ -uint16_t readADCChannel(uint8_t aChannelNumber) { +uint16_t readADCChannel(uint8_t aADCChannelNumber) { WordUnionForADCUtils tUValue; - ADMUX = aChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE); // ADCSRB = 0; // Only active if ADATE is set to 1. // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode @@ -88,9 +98,9 @@ uint16_t readADCChannel(uint8_t aChannelNumber) { /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. */ -uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference) { +uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) { WordUnionForADCUtils tUValue; - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); // ADCSRB = 0; // Only active if ADATE is set to 1. // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode @@ -109,18 +119,18 @@ uint16_t readADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference) * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. * Does NOT restore ADMUX after reading */ -uint16_t waitAndReadADCChannelWithReference(uint8_t aChannelNumber, uint8_t aReference) { - checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference); - return readADCChannelWithReference(aChannelNumber, aReference); +uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) { + checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference); + return readADCChannelWithReference(aADCChannelNumber, aReference); } /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. * Restores ADMUX after reading */ -uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aChannelNumber, uint8_t aReference) { - uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aChannelNumber, aReference); - uint16_t tResult = readADCChannelWithReference(aChannelNumber, aReference); +uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference) { + uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference); + uint16_t tResult = readADCChannelWithReference(aADCChannelNumber, aReference); checkAndWaitForReferenceAndChannelToSwitch(tOldADMUX & MASK_FOR_ADC_CHANNELS, tOldADMUX >> SHIFT_VALUE_FOR_REFERENCE); return tResult; } @@ -128,15 +138,15 @@ uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t a /* * To prepare reference and ADMUX for next measurement */ -void setADCMultiplexerAndReferenceForNextConversion(uint8_t aChannelNumber, uint8_t aReference) { - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); +void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference) { + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); } /* * @return original ADMUX register content for optional later restoring values * All experimental values are acquired by using the ADCSwitchingTest example from this library */ -uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8_t aReference) { +uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference) { uint8_t tOldADMUX = ADMUX; /* * Must wait >= 7 us if reference has to be switched from 1.1 volt/INTERNAL to VCC/DEFAULT (seen on oscilloscope) @@ -146,7 +156,7 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8 * Must wait >= 200 us if channel has to be switched to 1.1 volt internal channel if S&H was at 5 Volt */ uint8_t tNewReference = (aReference << SHIFT_VALUE_FOR_REFERENCE); - ADMUX = aChannelNumber | tNewReference; + ADMUX = aADCChannelNumber | tNewReference; #if defined(INTERNAL2V56) if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) { #else @@ -156,8 +166,8 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8 * Switch reference from DEFAULT to INTERNAL */ delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board - } else if ((tOldADMUX & 0x0F) != aChannelNumber) { - if (aChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) { + } else if ((tOldADMUX & 0x0F) != aADCChannelNumber) { + if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) { /* * Internal 1.1 Volt channel requires <= 200 us for Nano board */ @@ -176,16 +186,16 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aChannelNumber, uint8 * Oversample and multiple samples only makes sense if you expect a noisy input signal * It does NOT increase the precision of the measurement, since the ADC has insignificant noise */ -uint16_t readADCChannelWithOversample(uint8_t aChannelNumber, uint8_t aOversampleExponent) { - return readADCChannelWithReferenceOversample(aChannelNumber, DEFAULT, aOversampleExponent); +uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent) { + return readADCChannelWithReferenceOversample(aADCChannelNumber, DEFAULT, aOversampleExponent); } /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. */ -uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) { +uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) { uint16_t tSumValue = 0; - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag @@ -212,9 +222,9 @@ uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber, uint8_t a /* * Use ADC_PRESCALE32 which gives 26 us conversion time and good linearity for 16 MHz Arduino */ -uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) { +uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) { uint16_t tSumValue = 0; - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag @@ -241,9 +251,9 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aChannelNumber, uint8 * Returns sum of all sample values * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h. */ -uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) { +uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) { uint16_t tSumValue = 0; - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag @@ -267,12 +277,12 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aChannelNumber, uint8_t /* * use ADC_PRESCALE32 which gives 26 us conversion time and good linearity - * @return the maximum of aNumberOfSamples measurements. + * @return the maximum value of aNumberOfSamples samples. */ -uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) { +uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) { uint16_t tADCValue = 0; uint16_t tMaximum = 0; - ADMUX = aChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag @@ -298,33 +308,41 @@ uint16_t readADCChannelWithReferenceMax(uint8_t aChannelNumber, uint8_t aReferen /* * use ADC_PRESCALE32 which gives 26 us conversion time and good linearity + * @return the maximum value during aMicrosecondsToAquire measurement. */ -uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) { +uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) { uint16_t tNumberOfSamples = aMicrosecondsToAquire / 26; - return readADCChannelWithReferenceMax(aChannelNumber, aReference, tNumberOfSamples); + return readADCChannelWithReferenceMax(aADCChannelNumber, aReference, tNumberOfSamples); } /* * aMaxRetries = 255 -> try forever * @return (tMax + tMin) / 2 */ -uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDelay, uint8_t aAllowedDifference, - uint8_t aMaxRetries) { - int tValues[4]; +uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay, + uint8_t aAllowedDifference, uint8_t aMaxRetries) { + int tValues[4]; // last value is in tValues[3] int tMin; int tMax; - tValues[0] = readADCChannel(aChannelNumber); + /* + * Initialize first 4 values before checking + */ + tValues[0] = readADCChannelWithReference(aADCChannelNumber, aReference); for (int i = 1; i < 4; ++i) { - delay(aDelay); // Only 3 delays! - tValues[i] = readADCChannel(aChannelNumber); + if (aDelay != 0) { + delay(aDelay); // Minimum is only 3 delays! + } + tValues[i] = readADCChannelWithReference(aADCChannelNumber, aReference); } do { - // find min and max + /* + * Get min and max of the last 4 values + */ tMin = 1024; tMax = 0; - for (int i = 0; i < 4; ++i) { + for (uint_fast8_t i = 0; i < 4; ++i) { if (tValues[i] < tMin) { tMin = tValues[i]; } @@ -338,22 +356,44 @@ uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aChannelNumber, uint8_t aDe if ((tMax - tMin) <= aAllowedDifference) { break; } else { + /* + * Get next value + */ // Serial.print("Difference="); // Serial.println(tMax - tMin); - - // move values + // Move values to front for (int i = 0; i < 3; ++i) { tValues[i] = tValues[i + 1]; } - // and wait - delay(aDelay); - tValues[3] = readADCChannel(aChannelNumber); + // and wait before getting next value + if (aDelay != 0) { + delay(aDelay); + } + tValues[3] = readADCChannelWithReference(aADCChannelNumber, aReference); } if (aMaxRetries != 255) { aMaxRetries--; } } while (aMaxRetries > 0); +#if defined(LOCAL_DEBUG) + if(aMaxRetries == 0) { + Serial.print(F("No 4 equal values for difference ")); + Serial.print(aAllowedDifference); + Serial.print(F(" found ")); + Serial.print(tValues[0]); + Serial.print(' '); + Serial.print(tValues[1]); + Serial.print(' '); + Serial.print(tValues[2]); + Serial.print(' '); + Serial.println(tValues[3]); + } else { + Serial.print(aMaxRetries); + Serial.println(F(" retries left")); + } +#endif + return (tMax + tMin) / 2; } @@ -576,16 +616,14 @@ bool isVCCTooLowMultipleTimes() { return false; } - /* * Return true if VCC_EMERGENCY_STOP_MILLIVOLT (3 V) reached */ -bool isVCCTooLow(){ +bool isVCCTooLow() { return (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT); } - -void resetVCCTooLowMultipleTimes(){ +void resetVCCTooLowMultipleTimes() { sVCCTooLowCounter = 0; } @@ -598,41 +636,55 @@ void resetVCCTooLowMultipleTimes(){ * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). * @return true if 5 % overvoltage reached */ -bool isVCCTooHigh(){ +bool isVCCTooHigh() { readVCCVoltageMillivolt(); return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); } -bool isVCCTooHighSimple(){ +bool isVCCTooHighSimple() { readVCCVoltageMillivoltSimple(); return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); } /* + * Temperature sensor is enabled by selecting the appropriate channel. + * Different formula for 328P and 328PB! * !!! Function without handling of switched reference and channel.!!! - * Use it ONLY if you only use INTERNAL reference (call getTemperatureSimple()) in your program. + * Use it ONLY if you only use INTERNAL reference (e.g. only call getTemperatureSimple()) in your program. */ -float getTemperatureSimple(void) { +float getCPUTemperatureSimple(void) { #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) return 0.0; #else -// use internal 1.1 volt as reference - float tTemp = (readADCChannelWithReferenceMultiSamples(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2) - 317); - return (tTemp * (4 / 1.22)); + // use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-( + uint16_t tTempRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2); +#if defined(LOCAL_DEBUG) + Serial.print(F("TempRaw=")); + Serial.println(tTempRaw); +#endif + +#if defined(__AVR_ATmega328PB__) + tTempRaw -= 245; + return (float)tTempRaw; +#else + tTempRaw -= 317; + return (float) tTempRaw / 1.22; +#endif #endif } /* - * Handles reference and channel switching by introducing the appropriate delays. + * Handles usage of 1.1 V reference and channel switching by introducing the appropriate delays. */ float getTemperature(void) { + return getCPUTemperature(); +} +float getCPUTemperature(void) { #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) return 0.0; #else // use internal 1.1 volt as reference checkAndWaitForReferenceAndChannelToSwitch(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL); - // assume the signal has noise, but never verified :-( - float tTemp = (readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 1) - 317); - return (tTemp / 1.22); + return getCPUTemperatureSimple(); #endif } @@ -642,4 +694,7 @@ float getTemperature(void) { } #endif // defined(ADC_UTILS_ARE_AVAILABLE) +#if defined(LOCAL_DEBUG) +#undef LOCAL_DEBUG +#endif #endif // _ADC_UTILS_HPP diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 328db5b8d..3ec6be4cc 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -36,6 +36,11 @@ IRExtensionClass::IRExtensionClass(IRrecv *aIrReceiver) { MyIrReceiver = aIrReceiver; } +void IRExtensionClass::decode() { + Serial.println(F("Call decode()")); + MyIrReceiver->decode(); +} + void IRExtensionClass::resume() { Serial.println(F("Call resume()")); MyIrReceiver->resume(); diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h index 5c50fd5e4..700ad0ee3 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h @@ -39,6 +39,7 @@ class IRExtensionClass public: IRrecv * MyIrReceiver; IRExtensionClass(IRrecv * aIrReceiver); + void decode(); void resume(); }; diff --git a/src/IRremote.h b/src/IRremote.h index 90a91e4d1..26b1fe3b8 100644 --- a/src/IRremote.h +++ b/src/IRremote.h @@ -26,6 +26,7 @@ bool IRrecv::decode(decode_results *aResults) { Serial.println(F("This version is no longer supported!")); Serial.println(F("Please use one of the new code examples from the library,")); Serial.println(F(" available at \"File > Examples > Examples from Custom Libraries / IRremote\".")); + Serial.println(F("Or downgrade your library to version 2.6.0.")); Serial.println(); Serial.println(F("Start with the SimpleReceiver or SimpleSender example.")); Serial.println(); diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 872b9fb0a..782615561 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1093,7 +1093,6 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { /********************************************** * Uno R4 boards - * The FspTimer uses undocumented **********************************************/ #elif defined(ARDUINO_ARCH_RENESAS) #include "FspTimer.h" From c5f50ea53828d4e60c53fa0b23009957a68f42f1 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 28 Sep 2023 23:15:38 +0200 Subject: [PATCH 011/133] Examples and ESP32C3 --- .github/workflows/LibraryBuild.yml | 37 ++++++++++--------- examples/AllProtocolsOnLCD/ADCUtils.h | 19 +++++++--- examples/AllProtocolsOnLCD/ADCUtils.hpp | 26 +++++++++++-- .../AllProtocolsOnLCD/LiquidCrystal_I2C.cpp | 6 +-- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 2 +- .../IRDispatcherDemo/IRDispatcherDemo.ino | 22 +++++------ .../IRDispatcherDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/MicroGirs/PinDefinitionsAndMore.h | 2 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 2 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../ReceiverTimingAnalysis.ino | 18 ++++----- .../SendAndReceive/PinDefinitionsAndMore.h | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/SimpleSender/PinDefinitionsAndMore.h | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 2 +- src/IRProtocol.hpp | 5 --- src/LongUnion.h | 7 ++++ 28 files changed, 104 insertions(+), 76 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 2f2106972..5920adcb7 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -183,26 +183,26 @@ jobs: # build-properties: # the flags were put in compiler.cpp.extra_flags # IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -# - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll -# platform-url: http://drazzy.com/package_drazzy.com_index.json -# required-libraries: ATtinySerialOut -# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino -# build-properties: # the flags were put in compiler.cpp.extra_flags -# SimpleSender: -DSEND_PWM_BY_TIMER + - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER -# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled -# platform-url: http://drazzy.com/package_drazzy.com_index.json -# required-libraries: ATtinySerialOut -# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino -# build-properties: # the flags were put in compiler.cpp.extra_flags -# SimpleSender: -DSEND_PWM_BY_TIMER + - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER -# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz -# platform-url: http://drazzy.com/package_drazzy.com_index.json -# required-libraries: ATtinySerialOut -# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino -# build-properties: # the flags were put in compiler.cpp.extra_flags -# SimpleSender: -DSEND_PWM_BY_TIMER + - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER - arduino-boards-fqbn: MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json @@ -284,3 +284,4 @@ jobs: sketch-names: ${{ matrix.sketch-names }} sketches-exclude: ${{ matrix.sketches-exclude }} build-properties: ${{ toJson(matrix.build-properties) }} + cli-version: 0.33.0 # to avoid errors for ATTinyCore diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 1abe62a51..c32658c62 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -112,9 +112,6 @@ #error "No temperature channel definitions specified for this AVR CPU" #endif -extern float sVCCVoltage; -extern uint16_t sVCCVoltageMillivolt; - extern long sLastVCCCheckMillis; extern uint8_t sVCCTooLowCounter; @@ -124,7 +121,6 @@ uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t a uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference); uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent); void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference); -uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples); @@ -139,9 +135,7 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, ui */ float getVCCVoltageSimple(void); void readVCCVoltageSimple(void); -uint16_t getVCCVoltageMillivoltSimple(void); void readVCCVoltageMillivoltSimple(void); -float getVCCVoltage(void); void readVCCVoltage(void); uint16_t getVCCVoltageMillivolt(void); void readVCCVoltageMillivolt(void); @@ -163,4 +157,17 @@ bool isVCCTooHigh(); bool isVCCTooHighSimple(); #endif // defined(__AVR__) ... + +/* + * Variables and functions defined as dummies to allow for seamless compiling on non AVR platforms + */ +extern float sVCCVoltage; +extern uint16_t sVCCVoltageMillivolt; + +uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); + +uint16_t getVCCVoltageMillivoltSimple(void); +float getVCCVoltage(void); +float getCPUTemperature(void); + #endif // _ADC_UTILS_H diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 6d78bdd8f..c96ceb6a6 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -688,10 +688,28 @@ float getCPUTemperature(void) { #endif } -#elif defined(ARDUINO_ARCH_APOLLO3) // defined(ADC_UTILS_ARE_AVAILABLE) - void ADCUtilsDummyToAvoidBFDAssertions(){ - ; - } +#else // defined(ADC_UTILS_ARE_AVAILABLE) +// Dummy definition of functions defined in ADCUtils to compile examples without errors +/* + * Persistent storage for VCC value + */ +float sVCCVoltage; +uint16_t sVCCVoltageMillivolt; + +uint16_t getVCCVoltageMillivoltSimple(void){ + return 3300; +} + +uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber __attribute__((unused)), + uint8_t aReference __attribute__((unused)), uint8_t aOversampleExponent __attribute__((unused))) { + return 0; +} +float getCPUTemperature() { + return 20.0; +} +float getVCCVoltage() { + return 3.3; +} #endif // defined(ADC_UTILS_ARE_AVAILABLE) #if defined(LOCAL_DEBUG) diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp index f89c98109..2659ef41f 100644 --- a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp +++ b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp @@ -131,7 +131,7 @@ void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t line /********** high level commands, for the user! */ void LiquidCrystal_I2C::clear() { command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! + delayMicroseconds(1500); // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK if (_oled) setCursor(0, 0); } @@ -274,10 +274,10 @@ void LiquidCrystal_I2C::expanderWrite(uint8_t _data) { void LiquidCrystal_I2C::pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high - delayMicroseconds(1); // enable pulse must be >450ns +// delayMicroseconds(1); // enable pulse must be >450ns // AJ 20.9.23 not required for my LCD's expanderWrite(_data & ~En); // En low - delayMicroseconds(50); // commands need > 37us to settle +// delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's } // Alias functions diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 8a66d4fc8..678ac9696 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -55,31 +55,31 @@ #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" # if defined(ARDUINO_AVR_DIGISPARKPRO) -#define IR_INPUT_PIN 9 // PA3 - on Digispark board labeled as pin 9 +#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 # else -#define IR_INPUT_PIN 0 // PCINT0 +#define IR_RECEIVE_PIN 0 // PCINT0 # endif # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) -#define IR_INPUT_PIN 10 +#define IR_RECEIVE_PIN 10 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) -#define IR_INPUT_PIN 21 // INT0 +#define IR_RECEIVE_PIN 21 // INT0 # elif defined(ESP8266) -#define IR_INPUT_PIN 14 // D5 +#define IR_RECEIVE_PIN 14 // D5 # elif defined(ESP32) -#define IR_INPUT_PIN 15 +#define IR_RECEIVE_PIN 15 # elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) -#define IR_INPUT_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico +#define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico # elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico -#define IR_INPUT_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3) +#define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3) # else -#define IR_INPUT_PIN 2 // INT0 +#define IR_RECEIVE_PIN 2 // INT0 # endif #elif defined(USE_IRMP_LIBRARY) /* * IRMP version */ -#define IR_INPUT_PIN 2 +#define IR_RECEIVE_PIN 2 #define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used. #if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) #define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN @@ -159,7 +159,7 @@ void setup() { IRDispatcher.init(); // This just calls irmp_init() #if defined(USE_TINY_IR_RECEIVER) - Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_INPUT_PIN))); + Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN))); #else irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index 1ee2bf92b..410b3fde7 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -33,8 +33,8 @@ #include -#define IR_INPUT_PIN 2 -//#define IR_INPUT_PIN 3 +#define IR_RECEIVE_PIN 2 +//#define IR_RECEIVE_PIN 3 /* * Helper macro for getting a macro definition as string @@ -55,19 +55,19 @@ void setup() Serial.println(F("START " __FILE__ " from " __DATE__)); #if defined(EICRA) && defined(EIFR) && defined(EIMSK) -# if (IR_INPUT_PIN == 2) +# if (IR_RECEIVE_PIN == 2) EICRA |= _BV(ISC00); // interrupt on any logical change EIFR |= _BV(INTF0); // clear interrupt bit EIMSK |= _BV(INT0); // enable interrupt on next change -# elif (IR_INPUT_PIN == 3) +# elif (IR_RECEIVE_PIN == 3) EICRA |= _BV(ISC10); // enable interrupt on pin3 on both edges for ATmega328 EIFR |= _BV(INTF1); // clear interrupt bit EIMSK |= _BV(INT1); // enable interrupt on next change # endif #else - attachInterrupt(digitalPinToInterrupt(IR_INPUT_PIN), measureTimingISR, CHANGE); + attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE); #endif - Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_INPUT_PIN))); + Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN))); Serial.println(); } @@ -197,9 +197,9 @@ void loop() void IRAM_ATTR measureTimingISR() #else # if defined(EICRA) && defined(EIFR) && defined(EIMSK) -# if (IR_INPUT_PIN == 2) +# if (IR_RECEIVE_PIN == 2) ISR(INT0_vect) -# elif (IR_INPUT_PIN == 3) +# elif (IR_RECEIVE_PIN == 3) ISR(INT1_vect) # endif # else @@ -213,7 +213,7 @@ void measureTimingISR() /* * read level and give feedback */ - uint8_t tInputLevel = digitalRead(IR_INPUT_PIN); + uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN); digitalWrite(LED_BUILTIN, !tInputLevel); if (tMicrosDelta > 10000) diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index aa85fdddf..e7ce194a7 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -174,7 +174,7 @@ #define TONE_PIN 42 // Dummy for examples using it #elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_INPUT_PIN 8 +#define IR_RECEIVE_PIN 8 #define IR_SEND_PIN 9 #define TONE_PIN 10 // ADC2_0 #define APPLICATION_PIN 11 diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 093d2a8f4..c47d9db2b 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -39,11 +39,6 @@ //#define LOCAL_DEBUG // This enables debug output only for this file #endif -/* - * Check for additional characteristics of timing like length of mark for a constant mark protocol, - * where space length determines the bit value. Requires up to 194 additional bytes of program memory. - */ -//#define DECODE_STRICT_CHECKS /** \addtogroup Receiving Receiving IR data for multiple protocols * @{ */ diff --git a/src/LongUnion.h b/src/LongUnion.h index 1e09695ee..3559ac214 100644 --- a/src/LongUnion.h +++ b/src/LongUnion.h @@ -94,6 +94,7 @@ union LongUnion { int16_t Words[2]; uint32_t ULong; int32_t Long; + float Float; }; #endif // _LONG_UNION_H @@ -140,6 +141,12 @@ union LongLongUnion { int16_t Words[4]; uint64_t ULongLong; int64_t LongLong; +#if __DBL_MANT_DIG__== 24 + float Floats[2]; // 32 bit double, as for AVR +#else + // 64 bit double + double Double; +#endif }; #endif // _LONG_LONG_UNION_H From b1941ff4706015f9d18a8d8768d616c7d5dfb6fc Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 9 Oct 2023 11:37:56 +0200 Subject: [PATCH 012/133] Documentation --- README.md | 80 ++++++++++++++++++++++++--------------------- src/IRReceive.hpp | 2 +- src/IRSend.hpp | 9 ++++- src/IRremote.h | 9 +++++ src/IRremoteInt.h | 4 ++- src/ir_Kaseikyo.hpp | 23 +++++++------ src/ir_NEC.hpp | 24 +++++++------- 7 files changed, 87 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 1e35cc3d8..9be6d4323 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,7 @@ For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/ ```c++ #include +#define RECV_PIN 2 IRrecv irrecv(RECV_PIN); decode_results results; @@ -181,6 +182,7 @@ void loop() { ```c++ #include +#define IR_RECEIVE_PIN 2 void setup() { @@ -667,11 +669,11 @@ These macros must be defined in your program **before** the line `#include ` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | -| `DECODE_STRICT_CHECKS` | disabled | Check for additional characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. | +| `DECODE_STRICT_CHECKS` | disabled | Check for additional required characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. | | `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | | `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
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. | @@ -692,7 +694,7 @@ 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_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. | @@ -723,9 +725,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.**

-ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board. +Digispark boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the Digispark Pro board.
+ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore). + - Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc. -- Arduino Uno R4, but not yet tested, because of lack of a R4 board. +- Arduino Uno R4, but not yet tested, because of lack of a R4 board. **Sending does not work** on the `arduino:renesas_uno:unor4wifi`. - Teensy 1.0 / 1.0++ / 2.0 / 2++ / 3.0 / 3.1 / 3.2 / Teensy-LC - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries); Credits: PaulStoffregen (Teensy Team) - Sanguino - ATmega8, 48, 88, 168, 328 @@ -736,7 +740,7 @@ ATtiny and Digispark boards are only tested with the recommended [ATTinyCore](ht - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**) - ESP8266 -- ESP32 (ESP32 C3 since board package 2.0.2 from Espressif) +- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) - Sparkfun Pro Micro - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 @@ -758,37 +762,37 @@ The TinyReceiver example uses the **TinyReceiver** library, which can **only re The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). It can be adjusted here.
**Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.
-| Board/CPU | Receive
& PWM Timers| Hardware-PWM Pin | analogWrite()
pins occupied by timer | -|--------------------------------------------------------------------------|-------------------|---------------------|-----------------------| -| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore) | **1** | **6** | -| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **0**, 1 | **0**, 4 | **0**, 1 & 4 | -| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** | -| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore) | **1** | **9**, 8 - 15 | **8 - 15** | -| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore) | **TCB0** | **PA05** | -| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore) | **TCA0** | **PA3** | -| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore) | **TCA0**, TCD | % | -| [ATmega8](https://github.com/MCUdude/MiniCore) | **1** | **9** | +| Board/CPU | Receive
& PWM Timers| Hardware-PWM Pin | analogWrite()
pins occupied by timer | +|-|-|-|-| +| [ATtiny84](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x4.md) | **1** | **6** | | +| [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x5.md) | **0**, 1 | **0**, 4 | **0**, 1 & 4 | +| [ATtiny88 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x8.md) | **1** | **PB1 / 8** | **PB1 / 8 & PB2 / 9** | +| [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x7.md) | **1** | **9**, 8 - 15 | **8 - 15** | +| [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x04.md) | **TCB0** | **PA05** | +| [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md) | **TCA0** | **PA3** | +| [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x17.md) | **TCA0**, TCD | % | +| [ATmega8](https://github.com/MCUdude/MiniCore#supported-microcontrollers) | **1** | **9** | +| [ATmega1284](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2**, 3 | 13, 14, 6 | +| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2** | 13, **14** | +| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | **1** | **13** | +| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore#supported-microcontrollers) | **1** | **13** | +| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore#pinout ) | **1** | **13** | | ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** | -| [ATmega1284](https://github.com/MCUdude/MightyCore) | 1, **2**, 3 | 13, 14, 6 | -| [ATmega164, ATmega324, ATmega644](https://github.com/MCUdude/MightyCore) | 1, **2** | 13, **14** | -| [ATmega8535 ATmega16, ATmega32](https://github.com/MCUdude/MightyCore) | **1** | **13** | -| [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore) | **1** | **13** | -| [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore) | **1** | **13** | -| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | -| ATmega4809 | **TCB0** | **A4** | -| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | -| Zero (SAMD) | **TC3** | \*, **9** | -| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | -| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | +| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | | +| ATmega4809 | **TCB0** | **A4** | | +| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | | +| Zero (SAMD) | **TC3** | \*, **9** | | +| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | | +| [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | | | [Teensy 1.0](https://www.pjrc.com/teensy/pinout.html) | **1** | **17** | 15, 18 | | [Teensy 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, 3, **4_HS** | 9, **10**, 14 | 12 | | [Teensy++ 1.0 / 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, **2**, 3 | **1**, 16, 25 | 0 | | [Teensy-LC](https://www.pjrc.com/teensy/pinout.html) | **TPM1** | **16** | 17 | -| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | +| [Teensy 3.0 - 3.6](https://www.pjrc.com/teensy/pinout.html) | **CMT** | **5** | | | [Teensy 4.0 - 4.1](https://www.pjrc.com/teensy/pinout.html) | **FlexPWM1.3** | **8** | 7, 25 | -| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** | +| [BluePill / STM32F103C8T6](https://github.com/stm32duino/Arduino_Core_STM32) | **3** | % | **PA6 & PA7 & PB0 & PB1** | | [BluePill / STM32F103C8T6](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill) | **TIM4** | % | **PB6 & PB7 & PB8 & PB9** | -| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin | +| [RP2040 / Pi Pico](https://github.com/earlephilhower/arduino-pico) | [default alarm pool](https://raspberrypi.github.io/pico-sdk-doxygen/group__repeating__timer.html) | All pins | No pin | | [RP2040 / Mbed based](https://github.com/arduino/ArduinoCore-mbed) | Mbed Ticker | All pins | No pin | ### No timer required for sending @@ -868,16 +872,16 @@ Created with sigrok PulseView with IR_NEC decoder by DjordjeMandic.

# Quick comparison of 5 Arduino IR receiving libraries -[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**. - **This is a short comparison and may not be complete or correct.** I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.
-It is dated from **24.06.2022**. If you have complains about the data or request for extensions, please send a PM or open a discussion. +It is dated from **24.06.2022** and updated 10/2023. If you have complains about the data or request for extensions, please send a PM or open a discussion. + +[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**. -| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)
**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [Minimal NEC](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder) -|---------|------|-----------|--------|----------|----------|----------| -| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC | NEC + RC5 + Sony + Samsung | +| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)
**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver/TinyReceiver.ino) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder) +|-|-|-|-|-|-|-| +| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC + FAST | NEC + RC5 + Sony + Samsung | | Timing method receive | Timer2 or interrupt for pin 2 or 3 | **Interrupt** | Timer2 or interrupt for pin 2 or 3 | Timer2 | **Interrupt** | **Interrupt** | | Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay
Microseconds() | blocking wait with delay
Microseconds() | % | | Send pins| All | All | All ? | Timer dependent | All | % | @@ -889,8 +893,8 @@ It is dated from **24.06.2022**. If you have complains about the data or request | FLASH usage (simple NEC example with 5 prints) | 1820
(4300 for 15 main / 8000 for all 40 protocols)
(+200 for callback)
(+80 for interrupt at pin 2+3)| 1270
(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? | | RAM usage | 52
(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 | | Supported platforms | **avr, megaavr, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3
(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attach
Interrupt()** | **All platforms with attach
Interrupt()** | -| Last library update | 6/2022 | 4/2018 | 3/2022 | 6/2022 | 6/2022 | 2/2022 | -| Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 45 issues, no reaction for at least one year.** | Universal decoder and encoder.
Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. | +| Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 | +| Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 63 issues, 10 pull requests.* | Universal decoder and encoder.
Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. | \* The Hash protocol gives you a hash as code, which may be sufficient to distinguish your keys on the remote, but may not work with some protocols like Mitsubishi diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 227a3ce57..f466a7094 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -51,7 +51,7 @@ //#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start() // /* - * Check for additional characteristics of timing like length of mark for a constant mark protocol, + * Check for additional required characteristics of timing like length of mark for a constant mark protocol, * where space length determines the bit value. Requires up to 194 additional bytes of program memory. */ //#define DECODE_STRICT_CHECKS diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 708814698..0a8ac014d 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -935,6 +935,13 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas * This function may affect the state of feedback LED. * Period time is 26 us for 38.46 kHz, 27 us for 37.04 kHz, 25 us for 40 kHz. * On time is 8 us for 30% duty cycle + * + * The mark() function relies on the correct implementation of: + * delayMicroseconds() for pulse time, and micros() for pause time. + * The delayMicroseconds() of pulse time is guarded on AVR CPU's with noInterrupts() / interrupts(). + * At the start of pause time, interrupts are enabled once, the rest of the pause is also guarded on AVR CPU's with noInterrupts() / interrupts(). + * The maximum length of an interrupt during sending should not exceed 26 us - 8 us = 18 us, otherwise timing is disturbed. + * This disturbance is no problem, if the exceedance is small and does not happen too often. */ void IRsend::mark(uint16_t aMarkMicros) { @@ -1002,7 +1009,7 @@ void IRsend::mark(uint16_t aMarkMicros) { // 4.3 us from do{ to pin setting if sendPin is no constant digitalWriteFast(sendPin, HIGH); # endif - delayMicroseconds(periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait. + delayMicroseconds (periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait. /* * Output the PWM pause diff --git a/src/IRremote.h b/src/IRremote.h index 26b1fe3b8..3af3f5829 100644 --- a/src/IRremote.h +++ b/src/IRremote.h @@ -9,6 +9,15 @@ #include "IRremote.hpp" +#warning Thank you for using the IRremote library! +#warning It seems, that you are using a old version 2.0 code / example. +#warning This version is no longer supported! +#warning Please use one of the new code examples from the library available at "File > Examples > Examples from Custom Libraries / IRremote". +#warning Or downgrade your library to version 2.6.0. +#warning Start with the SimpleReceiver or SimpleSender example. +#warning The examples are documented here: https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library +#warning A guide how to convert your 2.0 program is here: https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version + /********************************************************************************************************************** * The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials * This function calls the old MSB first decoders and fills only the 3 variables: diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 7ff756e33..919712941 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -124,6 +124,8 @@ typedef uint64_t IRRawDataType; /* * Debug directives + * Outputs with IR_DEBUG_PRINT can only be activated by defining DEBUG! + * If LOCAL_DEBUG is defined in one file, all outputs with IR_DEBUG_PRINT are still suppressed. */ #if defined(DEBUG) || defined(TRACE) # define IR_DEBUG_PRINT(...) Serial.print(__VA_ARGS__) @@ -162,7 +164,7 @@ struct decode_results { uint16_t magnitude; // deprecated, moved to decodedIRData.extra ///< Used by MagiQuest [16-bits] bool isRepeat; // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected -// next 3 values are copies of irparams values - see IRremoteint.h +// next 3 values are copies of irparams_struct values - see above uint16_t *rawbuf; // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks uint_fast8_t rawlen; // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 294ea94e8..4c1b9b8d9 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -75,22 +75,21 @@ */ // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Panasonic // http://www.hifi-remote.com/johnsfine/DecodeIR.html#Kaseikyo +// LSB first // The first two (8-bit) bytes contains the vendor code. +// The next 4 bit is VendorID parity. +// The last byte is parity (XOR) of the 3 bytes before. // There are multiple interpretations of the next fields: // IRP: {37k,432}<1,-1|1,-3>(8,-4,M:8,N:8,X:4,D:4,S:8,F:8,G:8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4} -// 1. interpretation: After the vendor code, the next byte is 4 bit VendorID parity and 4 bit Device and Subdevice -// The 5th byte is the function and the last (6.th) byte is xor of the three bytes before it. -// 0_______ 1_______ 2______ 3_______ 4_______ 5 +// 1. interpretation: 4 bit Device, 8 bitSubdevice and 8 bit function. +// 0_______ 1_______ 2______ 3_______ 4_______ 5_______ // 01234567 89ABCDEF 01234567 01234567 01234567 01234567 -// 01000000 00100100 Dev____ Sub_Dev_ Fun____ XOR( B2, B3, B4) - showing Panasonic vendor code 0x2002 +// 01000000 00100100 0110Dev_ Sub_Dev_ Fun____ XOR( B2, B3, B4) - Byte 0,1 and vendor parity showing Panasonic vendor code 0x2002. +// 1. interpretation: // see: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -// -// 2. interpretation: LSB first, start bit + 16 VendorID + 4 VendorID parity + 4 Genre1 + 4 Genre2 + 10 Command + 2 ID + 8 Parity + stop bit +// 2. interpretation: // see: https://www.mikrocontroller.net/articles/IRMP_-_english#KASEIKYO -// 32 bit raw data LSB is VendorID parity. -// -// We reduce it to: IRP: {37k,432}<1,-1|1,-3>(8,-4,V:16,X:4,D:4,S:8,F:8,(X^D^S^F):8,1,-173)+ {X=M:4:0^M:4:4^N:4:0^N:4:4} -// start bit + 16 VendorID + 4 VendorID parity + 12 Address + 8 Command + 8 Parity of VendorID parity, Address and Command + stop bit +// Implemented is: // #define KASEIKYO_VENDOR_ID_BITS 16 #define KASEIKYO_VENDOR_ID_PARITY_BITS 4 @@ -140,9 +139,9 @@ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumb #if __INT_WIDTH__ < 32 LongUnion tSendValue; // Compute parity - tSendValue.UWord.LowWord = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble to parity + tSendValue.UWord.LowWord = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble with vendor parity tSendValue.UBytes[2] = aCommand; - tSendValue.UBytes[3] = aCommand ^ tSendValue.UBytes[0] ^ tSendValue.UBytes[1]; // Parity + tSendValue.UBytes[3] = aCommand ^ tSendValue.UBytes[0] ^ tSendValue.UBytes[1]; // 8 bit parity of 3 bytes command, address and vendor parity IRRawDataType tRawKaseikyoData[2]; tRawKaseikyoData[0] = (uint32_t) tSendValue.UWord.LowWord << 16 | aVendorCode; // LSB of tRawKaseikyoData[0] is sent first tRawKaseikyoData[1] = tSendValue.UWord.HighWord; diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index b68942537..a0627e68f 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -33,9 +33,9 @@ #define _IR_NEC_HPP #if defined(DEBUG) && !defined(LOCAL_DEBUG) -#define LOCAL_DEBUG +#define LOCAL_DEBUG // IR_DEBUG_PRINT is a real print function here. Add local debug output. #else -//#define LOCAL_DEBUG // This enables debug output only for this file +//#define LOCAL_DEBUG // This enables debug output only for this file. IR_DEBUG_PRINT is still a void function here. #endif /** \addtogroup Decoder Decoders and encoders for different protocols @@ -71,17 +71,20 @@ */ // http://www.hifi-remote.com/wiki/index.php/NEC // https://www.sbprojects.net/knowledge/ir/nec.php -// for Apple see https://en.wikipedia.org/wiki/Apple_Remote - Fixed address 0x87EE, 8 bit device ID, 7 bit command, 1 bit parity - untested! -// ONKYO like NEC but 16 independent address and command bits -// APPLE like ONKYO with special NEC repeat but with constant address of 0x87EE and and 16 bit command interpreted as MSB = 8 bit device ID, LSB = 8 bit command -// PIONEER (not implemented) is NEC2 with 40 kHz -// LSB first, 1 start bit + 16 bit address (or 8 bit address and 8 bit inverted address) + 8 bit command + 8 bit inverted command + 1 stop bit. +// NEC: LSB first, (or ) . +// ONKYO like NEC but 16 independent address and command bits: // Standard NEC sends a special fixed repeat frame. // NEC2 sends the same full frame after the 110 ms. I have a DVD remote with NEC2. // NEC and NEC 2 only differ in the repeat frames, so the protocol can only be detected correctly after the first repeat. +// PIONEER (not implemented) is NEC2 with 40 kHz // +// For Apple see https://en.wikipedia.org/wiki/Apple_Remote - <0x87EE:16> - not implemented! +// The parity is not implemented, so we get: <0x87EE:16> +// +// IRP notation: // IRP: NEC {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m,(16,-4,1,^108m)*) ==> "*" means send special repeat frames o ore more times // IRP: NEC2 {38.0k,564}<1,-1|1,-3>(16,-8,D:8,S:8,F:8,~F:8,1,^108m)+ ==> "+" means send frame 1 or more times (special repeat is missing here!) +// Interpretation of IRP notation: // {38.0k,564} ==> 38.0k -> Frequency , 564 -> unit in microseconds (we use 560), no "msb", so "lsb" is assumed // <1,-1|1,-3> ==> Zero is 1 unit mark and space | One is 1 unit mark and 3 units space // 16,-8 ==> Start bit durations @@ -137,7 +140,7 @@ void IRsend::sendNECRepeat() { } /** - * Static function for sending special repeat frame. + * Static function variant of IRsend::sendNECRepeat * For use in ProtocolConstants. Saves up to 250 bytes compared to a member function. */ void sendNECSpecialRepeat() { @@ -199,14 +202,13 @@ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumber * There is NO delay after the last sent repeat! * https://en.wikipedia.org/wiki/Apple_Remote * https://gist.github.com/darconeous/4437f79a34e3b6441628 - * @param aAddress is the DeviceId* * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { LongUnion tRawData; - // Address 16 bit LSB first + // Address 16 bit LSB first fixed value of 0x87EE tRawData.UWord.LowWord = APPLE_ADDRESS; // send Apple code and then 8 command bits LSB first @@ -217,7 +219,7 @@ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberO } /* - * Sends NEC1 protocol + * Sends NEC protocol * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ From c6aa13e4432d3a0f77f7e87a028337f27f352b5c Mon Sep 17 00:00:00 2001 From: Florian Meier Date: Mon, 16 Oct 2023 23:05:09 +0200 Subject: [PATCH 013/133] Fix wrong type of tEnableLEDFeedback in IRSend.hpp (#1177) tEnableLEDFeedback should not be a bool, because it's used as a bitmask with different states (Send/Receive/...). Even though a bool should be a byte anyways, this is apprently optimized with the current platformio toolchain for ESP8266 and causes the feedback LED to not work correctly. --- src/IRSend.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 0a8ac014d..420bbade9 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -95,7 +95,7 @@ void IRsend::begin(){ */ void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) { #if !defined(NO_LED_FEEDBACK_CODE) - bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; + uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if(aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND; } @@ -143,7 +143,7 @@ void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t #endif #if !defined(NO_LED_FEEDBACK_CODE) - bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; + uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if (aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND; } From 5a27b3ad4438da9bd9d3581c1864e343716e303d Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 16 Oct 2023 23:09:16 +0200 Subject: [PATCH 014/133] Fix wrong type of tEnableLEDFeedback in IRReceive.hpp --- README.md | 4 ++-- src/IRReceive.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9be6d4323..fe4ca9ab0 100644 --- a/README.md +++ b/README.md @@ -669,7 +669,7 @@ These macros must be defined in your program **before** the line `#include ` | 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) | @@ -694,7 +694,7 @@ 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_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. | diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index f466a7094..aa929229c 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -287,7 +287,7 @@ void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8 setReceivePin(aReceivePin); #if !defined(NO_LED_FEEDBACK_CODE) - bool tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; + uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if (aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE; } From 8c84e03318bf219fdbba910642acba87989d58d4 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 18 Oct 2023 20:30:29 +0200 Subject: [PATCH 015/133] Documentation --- README.md | 2 +- changelog.md | 3 +++ examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 9 +++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe4ca9ab0..688bc4920 100644 --- a/README.md +++ b/README.md @@ -740,7 +740,7 @@ ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/A - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**) - ESP8266 -- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) +- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) **not for ESP32 core version > 3.0.0** - Sparkfun Pro Micro - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 diff --git a/changelog.md b/changelog.md index c1bbb52bf..a995e2a18 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,9 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.2.1 +- Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. + # 4.2.0 - The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message. - Added DECODE_ONKYO, to force 16 bit command and data decoding. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index e26b64323..5aeeb13d9 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -95,7 +95,9 @@ LiquidCrystal myLCD(7, 8, 3, 4, 5, 6); #else #define DEBUG_BUTTON_PIN 6 #endif -#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug +#if defined(__AVR_ATmega328P__) +#define AUXILIARY_DEBUG_BUTTON_PIN 12 // Is set to low to enable using of a simple connector for enabling debug with pin 11 +#endif #define MILLIS_BETWEEN_ATTENTION_BEEP 60000 // 60 sec uint32_t sMillisOfLastReceivedIRFrame = 0; @@ -164,8 +166,11 @@ void setup() { # else Serial.print(DEBUG_BUTTON_PIN); # endif - Serial.print(F(" to ground or to pin ")); + Serial.print(F(" to ground")); +# if defined(AUXILIARY_DEBUG_BUTTON_PIN) + Serial.print(F(" or to pin ")); Serial.print(AUXILIARY_DEBUG_BUTTON_PIN); +#endif Serial.println(F(", raw data is always printed")); // infos for receive From f80a7df2445cbebbb5d050f2c82e188674e7af8d Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 2 Nov 2023 22:03:25 +0100 Subject: [PATCH 016/133] TinyReceiver 2.0 --- .github/workflows/LibraryBuild.yml | 62 +++- README.md | 29 +- changelog.md | 4 + examples/TinyReceiver/PinDefinitionsAndMore.h | 345 ++++++++++++++++++ examples/TinyReceiver/TinyReceiver.ino | 102 ++---- examples/TinySender/PinDefinitionsAndMore.h | 345 ++++++++++++++++++ examples/TinySender/TinySender.ino | 2 +- src/IRReceive.hpp | 5 +- src/IRremoteInt.h | 2 +- src/TinyIR.h | 59 +-- src/TinyIRReceiver.hpp | 64 ++-- src/ir_BangOlufsen.hpp | 5 +- src/private/IRTimer.hpp | 2 +- 13 files changed, 842 insertions(+), 184 deletions(-) create mode 100644 examples/TinyReceiver/PinDefinitionsAndMore.h create mode 100644 examples/TinySender/PinDefinitionsAndMore.h diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 5920adcb7..734432f14 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -1,7 +1,7 @@ # https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/.github/workflows/LibraryBuild.yml # Github workflow script to test compile all examples of an Arduino library repository. # -# Copyright (C) 2020 Armin Joachimsmeyer +# Copyright (C) 2020-2023 Armin Joachimsmeyer # https://github.com/ArminJo/Github-Actions # # Before being able to push to my .github\workflows directories, @@ -86,6 +86,7 @@ jobs: - arduino-boards-fqbn: arduino:avr:uno|DEBUG build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 + TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER All: -DEBUG - arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM @@ -131,7 +132,7 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 SimpleSender: -DSEND_PWM_BY_TIMER - TinyReceiver: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE + TinyReceiver: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE -DUSE_CALLBACK_FOR_TINY_RECEIVER TinySender: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE - arduino-boards-fqbn: arduino:samd:arduino_zero_native @@ -155,6 +156,9 @@ jobs: IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 SimpleSender: -DSEND_PWM_BY_TIMER +# +# RP2040 +# - arduino-boards-fqbn: arduino:mbed_rp2040:pico build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 @@ -167,6 +171,9 @@ jobs: SimpleSender: -DSEND_PWM_BY_TIMER All: -DRAW_BUFFER_LENGTH=700 +# +# megaTinyCore +# # https://github.com/SpenceKonde/megaTinyCore/issues/935 # - arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # arduino-platform: megaTinyCore:megaavr @@ -183,27 +190,33 @@ jobs: # build-properties: # the flags were put in compiler.cpp.extra_flags # IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 - - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# +# ATTinyCore +# +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER +# +# MegaCore +# - arduino-boards-fqbn: MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json arduino-platform: arduino:avr,MegaCore:avr # gcc is taken from arduino:avr @@ -212,6 +225,9 @@ jobs: SimpleSender: -DSEND_PWM_BY_TIMER All: -DRAW_BUFFER_LENGTH=700 +# +# ESP +# - arduino-boards-fqbn: esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80 platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json sketches-exclude: TinyReceiver @@ -226,6 +242,9 @@ jobs: IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 +# +# STM +# - arduino-boards-fqbn: STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 # ST version platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json sketches-exclude: TinyReceiver @@ -247,6 +266,9 @@ jobs: IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 All: -DRAW_BUFFER_LENGTH=300 +# +# Others +# - arduino-boards-fqbn: SparkFun:avr:promicro arduino-platform: arduino:avr,SparkFun:avr platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here diff --git a/README.md b/README.md index 688bc4920..3464c9b47 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,9 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-instead-of-cpp) - [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files) - [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes) - * [Data format](https://github.com/Arduino-IRremote/Arduino-IRremote#data-format) + * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote#decodedirdata-structure) * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#ambiguous-protocols) + * [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#unknown-protocol) - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes) * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote#send-pin) + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases) @@ -141,8 +142,8 @@ If you use an (old) Arduino core that does not use the `-flto` flag for compile, - Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar. - Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106) or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin(ENABLE_LED_FEEDBACK);` or `IrSender.begin(DISABLE_LED_FEEDBACK);` in setup().
-If IR_SEND_PIN is not defined you must use e.g. `IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);` +For sending, call `IrSender.begin();` or `IrSender.begin(DISABLE_LED_FEEDBACK);` 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);` - 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`. @@ -287,13 +288,12 @@ The following macros will definitely be overridden with default values otherwise
# Receiving IR codes -Check for **received data** with:
+Check for a **completly received IR frame** with:
`if (IrReceiver.decode()) {}`
-This also decodes the received data. - -## Data format +This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`. +## decodedIRData structure ```c++ struct IRData { decode_type_t protocol; // UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ... @@ -368,6 +368,9 @@ This behavior is quite unique for NEC and its derived protocols like LG. So there are of course also remote control systems, which uses the NEC protocol but on a long press just repeat the first frame instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
But be careful, the NEC2 protocol can only be detected by the NEC library decoder **after** the first frame and if you do a long press! +## Unknown protocol +If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP). +
# Sending IR codes @@ -417,12 +420,11 @@ void setup() { initPCIInterruptForTinyReceiver(); // Enables the interrupt generation on change of IR input signal } -void loop() {} - -// This is the function, which is called if a complete command was received -// It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here -void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) { - printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags); +void loop() { + if (TinyIRReceiverData.justWritten) { + TinyIRReceiverData.justWritten = false; + printTinyReceiverResultMinimal(&Serial); + } } ``` @@ -702,6 +704,7 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | | `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. | | `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. | +| `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. | The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | diff --git a/changelog.md b/changelog.md index a995e2a18..9236e5ceb 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,10 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. +- TinyReceiver 2.0 + - New TinyIRReceiverData which is filled with address, command and flags. + - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). + - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated. # 4.2.0 - The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message. diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h new file mode 100644 index 000000000..e7ce194a7 --- /dev/null +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -0,0 +1,345 @@ +/* + * 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 + * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore + * ATtiny1604 2 3|PA5 % + * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore + * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore + * SAMD21 3 4 5 + * ESP8266 14|D5 12|D6 % + * ESP32 15 4 27 + * BluePill PA6 PA7 PA3 + * APOLLO3 11 12 5 + * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 + */ +//#define _IR_MEASURE_TIMING // For debugging purposes. + +#if defined(__AVR__) +#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. +#define IR_RECEIVE_PIN PIN_PB0 +#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. +#define TONE_PIN PIN_PB3 +#define _IR_TIMING_TEST_PIN PIN_PB3 + +# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" +// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. +# if defined(ARDUINO_AVR_DIGISPARKPRO) +// For use with Digispark original core +#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 +//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 +#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 +#define _IR_TIMING_TEST_PIN 10 // PA4 +# else +// For use with ATTinyCore +#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 +#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 +# endif + +# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +#define IR_RECEIVE_PIN PIN_PB2 // INT0 +#define IR_SEND_PIN PIN_PA4 +#define TONE_PIN PIN_PA3 +#define _IR_TIMING_TEST_PIN PIN_PA5 + +# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +// Pin 6 is TX, pin 7 is RX +#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 +#define IR_SEND_PIN PIN_PD4 // 4 +#define TONE_PIN PIN_PB1 // 9 +#define _IR_TIMING_TEST_PIN PIN_PB0 // 8 + +# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore +// Tiny Core Dev board +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ +#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +#define IR_SEND_PIN PIN_PA2 // 19 +#define TONE_PIN PIN_PA3 // 20 +#define APPLICATION_PIN PIN_PA0 // 0 +#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output +#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 + +# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 14 +#define IR_SEND_PIN PIN_PA1 // 16 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 +#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output +#define LED_BUILTIN PIN_PB5 // 4 + +# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA3 // 10 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN PIN_PA7 // 3 +#define APPLICATION_PIN PIN_PB2 // 5 + +#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ +|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ +|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ +|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ +|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ +|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ +|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ +|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ +|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 13 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. +#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit +// We have no built in LED at pin 13 -> reuse RX LED +#undef LED_BUILTIN +#define LED_BUILTIN LED_BUILTIN_RX +# endif +# endif // defined(__AVR_ATtiny25__)... + +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 +// To be compatible with Uno R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ESP8266) +#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW +#define IR_RECEIVE_PIN 14 // D5 +#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED +#define _IR_TIMING_TEST_PIN 2 // D4 +#define APPLICATION_PIN 13 // D7 + +#define tone(...) void() // tone() inhibits receive timer +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) +#define IR_RECEIVE_PIN 8 +#define IR_SEND_PIN 9 +#define TONE_PIN 10 // ADC2_0 +#define APPLICATION_PIN 11 + +#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 ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) +#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer. +void tone(uint8_t aPinNumber, unsigned int aFrequency){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); +} +void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); + delay(aDuration); + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +void noTone(uint8_t aPinNumber){ + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) + +#define IR_RECEIVE_PIN 15 // D15 +#define IR_SEND_PIN 4 // D4 +#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 +#define APPLICATION_PIN 16 // RX2 pin + +#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill +// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() +#define IR_RECEIVE_PIN PA6 +#define IR_RECEIVE_PIN_STRING "PA6" +#define IR_SEND_PIN PA7 +#define IR_SEND_PIN_STRING "PA7" +#define TONE_PIN PA3 +#define _IR_TIMING_TEST_PIN PA5 +#define APPLICATION_PIN PA2 +#define APPLICATION_PIN_STRING "PA2" +# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) +// BluePill LED is active low +#define FEEDBACK_LED_IS_ACTIVE_LOW +# endif + +#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards +#define IR_RECEIVE_PIN 11 +#define IR_SEND_PIN 12 +#define TONE_PIN 5 + +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico +#define IR_SEND_PIN 4 // GPIO16 +#define TONE_PIN 5 +#define APPLICATION_PIN 6 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 8 + +#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico +#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3) +#define IR_SEND_PIN 16 // GPIO16 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 20 + +// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN +// and use the external reset with 1 kOhm to ground to enter UF2 mode +#undef LED_BUILTIN +#define LED_BUILTIN 6 + +#elif defined(PARTICLE) // !!!UNTESTED!!! +#define IR_RECEIVE_PIN A4 +#define IR_SEND_PIN A5 // Particle supports multiple pins + +#define LED_BUILTIN D7 + +/* + * 4 times the same (default) layout for easy adaption in the future + */ +#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) +// On the Zero and others we switch explicitly to SerialUSB +#define Serial SerialUSB +#endif + +// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17. +// Attention!!! D2 and D4 are swapped on these boards!!! +// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 24 // PB11 +// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 25 // PB03 +//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW + +#elif defined (NRF51) // BBC micro:bit +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define APPLICATION_PIN 1 +#define _IR_TIMING_TEST_PIN 4 + +#define tone(...) void() // no tone() available +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#else +#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h. +// Default valued for unidentified boards +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 +#endif // defined(ESP8266) + +#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) +#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation +#else +# if defined(SEND_PWM_BY_TIMER) +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +# endif +#endif + +#if !defined (FLASHEND) +#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined +#endif +#if !defined (RAMEND) +#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined +#endif + +/* + * Helper macro for getting a macro definition as string + */ +#if !defined(STR_HELPER) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index cbf6188f3..9ded911f1 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -50,49 +50,21 @@ #include -/* - * Set sensible receive pin for different CPU's - */ -#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) -/* - * This program runs on 1 MHz CPU clock :-) and is requires only 1550 bytes program memory using ATTiny core - */ -#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut" - Saves up to 700 bytes program memory and 70 bytes RAM for ATtinyCore -# if defined(ARDUINO_AVR_DIGISPARKPRO) -#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 -# else -#define IR_RECEIVE_PIN 0 // PCINT0 -# endif -#elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) -#define IR_RECEIVE_PIN 10 -#elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) -#define IR_RECEIVE_PIN 21 // INT0 -#elif defined(ESP8266) -#define IR_RECEIVE_PIN 14 // D5 -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#elif defined(ESP32) -#define IR_RECEIVE_PIN 15 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) -#define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico -#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico -#define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3) -#else -#define IR_RECEIVE_PIN 2 // INT0 -//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt. -#endif +#include "PinDefinitionsAndMore.h" // Set IR_RECEIVE_PIN for different CPU's //#define DEBUG // to see if attachInterrupt is used //#define TRACE // to see the state of the ISR state machine /* - * Second: include the code and compile it. + * Set compile options to modify the generated code. */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. -#include "TinyIRReceiver.hpp" +//#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. + +#include "TinyIRReceiver.hpp" // include the code /* * Helper macro for getting a macro definition as string @@ -102,8 +74,6 @@ #define STR(x) STR_HELPER(x) #endif -volatile struct TinyIRReceiverCallbackDataStruct sCallbackData; - void setup() { Serial.begin(115200); #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) @@ -127,20 +97,20 @@ void setup() { } void loop() { - if (sCallbackData.justWritten) { - sCallbackData.justWritten = false; -#if defined(USE_FAST_PROTOCOL) - Serial.print(F("Command=0x")); -#else + if (TinyIRReceiverData.justWritten) { + TinyIRReceiverData.justWritten = false; +#if !defined(USE_FAST_PROTOCOL) + // We have no address at FAST protocol Serial.print(F("Address=0x")); - Serial.print(sCallbackData.Address, HEX); - Serial.print(F(" Command=0x")); + Serial.print(TinyIRReceiverData.Address, HEX); + Serial.print(' '); #endif - Serial.print(sCallbackData.Command, HEX); - if (sCallbackData.Flags == IRDATA_FLAGS_IS_REPEAT) { + Serial.print(F("Command=0x")); + Serial.print(TinyIRReceiverData.Command, HEX); + if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) { Serial.print(F(" Repeat")); } - if (sCallbackData.Flags == IRDATA_FLAGS_PARITY_FAILED) { + if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) { Serial.print(F(" Parity failed")); } Serial.println(); @@ -151,40 +121,30 @@ void loop() { } /* - * This is the function, which is called if a complete command was received + * Optional code, if you require a callback + */ +#if defined(USE_CALLBACK_FOR_TINY_RECEIVER) +/* + * This is the function, which is called if a complete frame was received * It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here */ -#if defined(ESP8266) || defined(ESP32) +# if defined(ESP8266) || defined(ESP32) IRAM_ATTR -#endif - -#if defined(USE_FAST_PROTOCOL) -void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags) -#elif defined(USE_ONKYO_PROTOCOL) -void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags) -#else -void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) -#endif - { -#if defined(ARDUINO_ARCH_MBED) || defined(ESP32) - // Copy data for main loop, this is the recommended way for handling a callback :-) -# if !defined(USE_FAST_PROTOCOL) - sCallbackData.Address = aAddress; # endif - sCallbackData.Command = aCommand; - sCallbackData.Flags = aFlags; - sCallbackData.justWritten = true; -#else + +void handleReceivedTinyIRData() { +# if defined(ARDUINO_ARCH_MBED) || defined(ESP32) /* - * Printing is not allowed in ISR context for any kind of RTOS + * Printing is not allowed in ISR context for any kind of RTOS, so we use the slihjtly more complex, + * but recommended way for handling a callback :-). Copy data for main loop. * For Mbed we get a kernel panic and "Error Message: Semaphore: 0x0, Not allowed in ISR context" for Serial.print() * for ESP32 we get a "Guru Meditation Error: Core 1 panic'ed" (we also have an RTOS running!) */ - // Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon -# if defined(USE_FAST_PROTOCOL) - printTinyReceiverResultMinimal(&Serial, aCommand, aFlags); + // Do something useful here... # else - printTinyReceiverResultMinimal(&Serial, aAddress, aCommand, aFlags); + // As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon + printTinyReceiverResultMinimal(&Serial); # endif -#endif } +#endif + diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h new file mode 100644 index 000000000..e7ce194a7 --- /dev/null +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -0,0 +1,345 @@ +/* + * 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 + * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore + * ATtiny1604 2 3|PA5 % + * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore + * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore + * SAMD21 3 4 5 + * ESP8266 14|D5 12|D6 % + * ESP32 15 4 27 + * BluePill PA6 PA7 PA3 + * APOLLO3 11 12 5 + * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 + */ +//#define _IR_MEASURE_TIMING // For debugging purposes. + +#if defined(__AVR__) +#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. +#define IR_RECEIVE_PIN PIN_PB0 +#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. +#define TONE_PIN PIN_PB3 +#define _IR_TIMING_TEST_PIN PIN_PB3 + +# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" +// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. +# if defined(ARDUINO_AVR_DIGISPARKPRO) +// For use with Digispark original core +#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 +//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 +#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 +#define _IR_TIMING_TEST_PIN 10 // PA4 +# else +// For use with ATTinyCore +#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 +#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 +# endif + +# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +#define IR_RECEIVE_PIN PIN_PB2 // INT0 +#define IR_SEND_PIN PIN_PA4 +#define TONE_PIN PIN_PA3 +#define _IR_TIMING_TEST_PIN PIN_PA5 + +# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +// Pin 6 is TX, pin 7 is RX +#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 +#define IR_SEND_PIN PIN_PD4 // 4 +#define TONE_PIN PIN_PB1 // 9 +#define _IR_TIMING_TEST_PIN PIN_PB0 // 8 + +# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore +// Tiny Core Dev board +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ +#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +#define IR_SEND_PIN PIN_PA2 // 19 +#define TONE_PIN PIN_PA3 // 20 +#define APPLICATION_PIN PIN_PA0 // 0 +#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output +#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 + +# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 14 +#define IR_SEND_PIN PIN_PA1 // 16 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 +#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output +#define LED_BUILTIN PIN_PB5 // 4 + +# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA3 // 10 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN PIN_PA7 // 3 +#define APPLICATION_PIN PIN_PB2 // 5 + +#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ +|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ +|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ +|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ +|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ +|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ +|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ +|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ +|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 13 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. +#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit +// We have no built in LED at pin 13 -> reuse RX LED +#undef LED_BUILTIN +#define LED_BUILTIN LED_BUILTIN_RX +# endif +# endif // defined(__AVR_ATtiny25__)... + +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 +// To be compatible with Uno R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ESP8266) +#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW +#define IR_RECEIVE_PIN 14 // D5 +#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED +#define _IR_TIMING_TEST_PIN 2 // D4 +#define APPLICATION_PIN 13 // D7 + +#define tone(...) void() // tone() inhibits receive timer +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) +#define IR_RECEIVE_PIN 8 +#define IR_SEND_PIN 9 +#define TONE_PIN 10 // ADC2_0 +#define APPLICATION_PIN 11 + +#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 ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) +#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer. +void tone(uint8_t aPinNumber, unsigned int aFrequency){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); +} +void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); + delay(aDuration); + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +void noTone(uint8_t aPinNumber){ + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) + +#define IR_RECEIVE_PIN 15 // D15 +#define IR_SEND_PIN 4 // D4 +#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 +#define APPLICATION_PIN 16 // RX2 pin + +#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill +// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() +#define IR_RECEIVE_PIN PA6 +#define IR_RECEIVE_PIN_STRING "PA6" +#define IR_SEND_PIN PA7 +#define IR_SEND_PIN_STRING "PA7" +#define TONE_PIN PA3 +#define _IR_TIMING_TEST_PIN PA5 +#define APPLICATION_PIN PA2 +#define APPLICATION_PIN_STRING "PA2" +# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) +// BluePill LED is active low +#define FEEDBACK_LED_IS_ACTIVE_LOW +# endif + +#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards +#define IR_RECEIVE_PIN 11 +#define IR_SEND_PIN 12 +#define TONE_PIN 5 + +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico +#define IR_SEND_PIN 4 // GPIO16 +#define TONE_PIN 5 +#define APPLICATION_PIN 6 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 8 + +#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico +#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3) +#define IR_SEND_PIN 16 // GPIO16 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 20 + +// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN +// and use the external reset with 1 kOhm to ground to enter UF2 mode +#undef LED_BUILTIN +#define LED_BUILTIN 6 + +#elif defined(PARTICLE) // !!!UNTESTED!!! +#define IR_RECEIVE_PIN A4 +#define IR_SEND_PIN A5 // Particle supports multiple pins + +#define LED_BUILTIN D7 + +/* + * 4 times the same (default) layout for easy adaption in the future + */ +#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) +// On the Zero and others we switch explicitly to SerialUSB +#define Serial SerialUSB +#endif + +// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17. +// Attention!!! D2 and D4 are swapped on these boards!!! +// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 24 // PB11 +// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 25 // PB03 +//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW + +#elif defined (NRF51) // BBC micro:bit +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define APPLICATION_PIN 1 +#define _IR_TIMING_TEST_PIN 4 + +#define tone(...) void() // no tone() available +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#else +#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h. +// Default valued for unidentified boards +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 +#endif // defined(ESP8266) + +#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) +#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation +#else +# if defined(SEND_PWM_BY_TIMER) +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +# endif +#endif + +#if !defined (FLASHEND) +#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined +#endif +#if !defined (RAMEND) +#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined +#endif + +/* + * Helper macro for getting a macro definition as string + */ +#if !defined(STR_HELPER) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 39ff3c4d7..970d00267 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -52,7 +52,7 @@ #include "TinyIRSender.hpp" -#define IR_SEND_PIN 3 +#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index aa929229c..fee76b27f 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -407,10 +407,11 @@ bool IRrecv::isIdle() { } /** - * Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame + * Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame. + * Counting of gap timing is independent of StateForISR and therefore independent of call time of resume(). */ void IRrecv::resume() { - // check allows to call resume at arbitrary places or more than once + // This check allows to call resume at arbitrary places or more than once if (irparams.StateForISR == IR_REC_STATE_STOP) { irparams.StateForISR = IR_REC_STATE_IDLE; } diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 919712941..10d87de8e 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -100,7 +100,7 @@ struct irparams_struct { volatile uint8_t *IRReceivePinPortInputRegister; uint8_t IRReceivePinMask; #endif - volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. + volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is independent of state or resume(). #if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP #endif diff --git a/src/TinyIR.h b/src/TinyIR.h index cc17bc357..c274b936e 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -34,9 +34,9 @@ * @{ */ -#define VERSION_TINYIR "1.2.0" -#define VERSION_TINYIR_MAJOR 1 -#define VERSION_TINYIR_MINOR 2 +#define VERSION_TINYIR "2.0.0" +#define VERSION_TINYIR_MAJOR 2 +#define VERSION_TINYIR_MINOR 0 #define VERSION_TINYIR_PATCH 0 // The change log is at the bottom of the file @@ -77,15 +77,15 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. */ /* -Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first + Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first +2100,-1050 + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550 + 550 -Sum: 28900 -*/ + Sum: 28900 + */ #define FAST_KHZ 38 #define FAST_ADDRESS_BITS 0 // No address #define FAST_COMMAND_BITS 16 // Command and inverted command (parity) @@ -158,36 +158,12 @@ Sum: 28900 #define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE #endif +#if defined(USE_CALLBACK_FOR_TINY_RECEIVER) /* - * This function is called, if a complete command was received and must be implemented in the file (user code) which includes this library. - * The parameter size is dependent of the code variant used in order to save program memory. - * We have 6 cases: 0, 8 bit or 16 bit address, each with 8 or 16 bit command + * This function is called, if a complete command was received and must be implemented in the file (user code) + * which includes this library if USE_CALLBACK_FOR_TINY_RECEIVER is activated. */ -#if (TINY_RECEIVER_ADDRESS_BITS > 0) -# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY -// 8 bit address here -# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY -extern void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags); // Standard NEC callback -# else -extern void handleReceivedTinyIRData(uint8_t aAddress, uint16_t aCommand, uint8_t aFlags); // If SUPPORT_ONKYO_16_BIT_COMMAND is defined -# endif - -# else // TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY -// 16 bit address here -# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY -extern void handleReceivedTinyIRData(uint16_t aAddress, uint8_t aCommand, uint8_t aFlags); -# else -extern void handleReceivedTinyIRData(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags); -# endif -# endif - -#else -// FAST protocol - No address here -# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY -extern void handleReceivedTinyIRData(uint8_t aCommand, uint8_t aFlags); // Standard FAST callback -# else -extern void handleReceivedTinyIRData(uint16_t aCommand, uint8_t aFlags); // If "TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false" is defined. 16 bit without parity. -# endif +extern void handleReceivedTinyIRData(); #endif #if !defined(MICROS_IN_ONE_SECOND) @@ -248,8 +224,7 @@ struct TinyIRReceiverStruct { #define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check /** - * Can be used by the callback to transfer received data to main loop for further processing. - * E.g. with volatile struct TinyIRReceiverCallbackDataStruct sCallbackData; + * Is filled before calling the user callback to transfer received data to main loop for further processing. */ struct TinyIRReceiverCallbackDataStruct { #if (TINY_RECEIVER_ADDRESS_BITS > 0) @@ -268,16 +243,13 @@ struct TinyIRReceiverCallbackDataStruct { uint8_t Flags; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bool justWritten; ///< Is set true if new data is available. Used by the main loop, to avoid multiple evaluations of the same IR frame. }; +extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; bool initPCIInterruptForTinyReceiver(); bool enablePCIInterruptForTinyReceiver(); void disablePCIInterruptForTinyReceiver(); bool isTinyReceiverIdle(); -#if defined(USE_FAST_PROTOCOL) -void printTinyReceiverResultMinimal(Print *aSerial, uint16_t aCommand, uint8_t aFlags); -#else -void printTinyReceiverResultMinimal(Print *aSerial, uint8_t aAddress, uint8_t aCommand, uint8_t aFlags); -#endif +void printTinyReceiverResultMinimal(Print *aSerial); void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); @@ -287,6 +259,11 @@ 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); /* + * Version 2.0.0 - 10/2023 + * - New TinyIRReceiverData which is filled with address, command and flags. + * - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). + * - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated. + * * Version 1.2.0 - 01/2023 * - Added ONKYO protocol, NEC with 16 bit address and command, instead of 8 bit + 8 bit parity address and command. * - Renamed functions and macros. diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 42905bb44..f81d71cf2 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -61,6 +61,7 @@ * - USE_ONKYO_PROTOCOL Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. * - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. * - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. + * - USE_CALLBACK_FOR_TINY_RECEIVER Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. */ #ifndef _TINY_IR_RECEIVER_HPP @@ -100,6 +101,7 @@ //#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement. //#define _IR_TIMING_TEST_PIN 7 TinyIRReceiverStruct TinyIRReceiverControl; +volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; /* * Set input pin and output pin definitions etc. @@ -143,7 +145,7 @@ TinyIRReceiverStruct TinyIRReceiverControl; * Declaration of the callback function provided by the user application. * It is called every time a complete IR command or repeat was received. */ -extern void handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, bool isRepetition); +extern void handleTinyReceivedIRData(); #if defined(LOCAL_DEBUG) uint32_t sMicrosOfGap; // The length of the gap before the start bit @@ -319,7 +321,7 @@ void IRPinChangeInterruptHandler(void) { */ if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) { #if defined(ENABLE_NEC2_REPEATS) - TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set + TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set #else TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; // here we do not check anything, if we have a repeat #endif @@ -332,15 +334,15 @@ void IRPinChangeInterruptHandler(void) { #if (TINY_RECEIVER_ADDRESS_BITS > 0) if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) { #if defined(ENABLE_NEC2_REPEATS) - TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; + TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; #else TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; #endif # if defined(LOCAL_DEBUG) - Serial.print(F("Parity check for command failed. Command=")); - Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); - Serial.print(F(" parity=")); - Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); + Serial.print(F("Parity check for command failed. Command=")); + Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); + Serial.print(F(" parity=")); + Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); # endif #else // No address, so command and parity are in the lowest bytes @@ -363,34 +365,37 @@ void IRPinChangeInterruptHandler(void) { #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running! interrupts(); // enable interrupts, so delay() etc. works in callback #endif - handleReceivedTinyIRData( + TinyIRReceiverData.justWritten = true; + TinyIRReceiverData.Flags = TinyIRReceiverControl.Flags; #if (TINY_RECEIVER_ADDRESS_BITS > 0) # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY - // Here we have 8 bit address - TinyIRReceiverControl.IRRawData.UBytes[0], + // Here we have 8 bit address + TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UBytes[0]; # else - // Here we have 16 bit address - TinyIRReceiverControl.IRRawData.UWord.LowWord, + // Here we have 16 bit address + TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UWord.LowWord; # endif # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY - // Here we have 8 bit command - TinyIRReceiverControl.IRRawData.UBytes[2], + // Here we have 8 bit command + TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[2]; # else // Here we have 16 bit command - TinyIRReceiverControl.IRRawData.UWord.HighWord, + TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord.HighWord; # endif -#else - // Here we have NO address +#else + // Here we have NO address # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY - // Here we have 8 bit command - TinyIRReceiverControl.IRRawData.UBytes[0], + // Here we have 8 bit command + TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[0]; # else - // Here we have 16 bit command - TinyIRReceiverControl.IRRawData.UWord, + // Here we have 16 bit command + TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord; # endif #endif - TinyIRReceiverControl.Flags); +#if defined(USE_CALLBACK_FOR_TINY_RECEIVER) + handleReceivedTinyIRData(); +#endif } else { // not finished yet @@ -429,27 +434,22 @@ bool initPCIInterruptForTinyReceiver() { return enablePCIInterruptForTinyReceiver(); } -#if defined(USE_FAST_PROTOCOL) -void printTinyReceiverResultMinimal(Print *aSerial, uint16_t aCommand, uint8_t aFlags) -#else -void printTinyReceiverResultMinimal(Print *aSerial, uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) -#endif - { +void printTinyReceiverResultMinimal(Print *aSerial) { // Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon // Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon #if defined(USE_FAST_PROTOCOL) aSerial->print(F("C=0x")); #else aSerial->print(F("A=0x")); - aSerial->print(aAddress, HEX); + aSerial->print(TinyIRReceiverData.Address, HEX); aSerial->print(F(" C=0x")); #endif - aSerial->print(aCommand, HEX); - if (aFlags == IRDATA_FLAGS_IS_REPEAT) { + aSerial->print(TinyIRReceiverData.Command, HEX); + if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) { aSerial->print(F(" R")); } #if !defined(DISABLE_PARITY_CHECKS) - if (aFlags == IRDATA_FLAGS_PARITY_FAILED) { + if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) { aSerial->print(F(" P")); } #endif diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 3ccaad451..9fa34a024 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -77,7 +77,7 @@ // !!! We assume that the real implementations never set the official first header bit to anything other than 0 !!! // !!! We therefore use 4 start bits instead of the specified 3 and in turn ignore the first header bit of the specification !!! -// IR messages are 16 bits long and datalink messages have different lengths +// IR messages are 16 bits long. Datalink messages have different lengths. // This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length // Header data with more than 16 bits is stored in decodedIRData.extra @@ -87,8 +87,9 @@ /* * Options for this decoder + * */ -//#define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory. +#define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory. Enabled by default, see https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1181 //#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory. #if defined(DECODE_BEO) # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 782615561..b47d733aa 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -180,7 +180,7 @@ void disableSendPWMByTimer() { #elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D) -#define IR_USE_AVR_TIMER_A // use this if you use MegaTinyCore, Tone is on TCB and millis() on TCD +#define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD //#define IR_USE_AVR_TIMER_D // use this if you use TinyCore # endif From 1008347e33924fc58815fc9726dfccb9aee1b483 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 4 Dec 2023 09:53:09 +0100 Subject: [PATCH 017/133] Documentation --- README.md | 6 ++- .../IRDispatcherDemo/IRCommandDispatcher.hpp | 38 ++++++++---------- .../IRDispatcherDemo/IRDispatcherDemo.ino | 26 ------------ examples/ReceiveDemo/ReceiveDemo.ino | 6 ++- pictures/IR_UnitTest_delay.bmp | Bin 0 -> 1200054 bytes 5 files changed, 25 insertions(+), 51 deletions(-) create mode 100644 pictures/IR_UnitTest_delay.bmp diff --git a/README.md b/README.md index 3464c9b47..a19284ef2 100644 --- a/README.md +++ b/README.md @@ -648,6 +648,8 @@ Click on the receiver while simulation is running to specify individual NEC IR c #### UnitTest ReceiveDemo + SendDemo in one program. Demonstrates **receiving while sending**. +Here you see the delay of the receiver output (blue) from the IR diode input (yellow). +![Delay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_UnitTest_delay.bmp) # WOKWI online examples - [Simple receiver](https://wokwi.com/projects/338611596994544210) @@ -846,7 +848,7 @@ Since each hardware timer has its dedicated output pin(s), you must change timer **Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/39bdf8d7bf5b90dc221f8ae9fb3efed9f0a8a1db/examples/SimpleSender/PinDefinitionsAndMore.h#L273), where **PWM generation does not require a timer**. ## Why do we use 30% duty cycle for sending -We do it according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf): +We [do it](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRSend.hpp#L1192) according to the statement in the [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf): - Carrier duty cycle 50 %, peak current of emitter IF = 200 mA, the resulting transmission distance is 25 m. - Carrier duty cycle 10 %, peak current of emitter IF = 800 mA, the resulting transmission distance is 29 m. - Factor 1.16 The reason is, that it is not the pure energy of the fundamental which is responsible for the receiver to detect a signal. @@ -859,7 +861,7 @@ The IR signal is sampled at a **50 µs interval**. For a constant 525 &micr And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
-And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value]/https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown) +And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library) 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**. diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp index f2bc25982..a11174e68 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp +++ b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp @@ -57,9 +57,6 @@ IRCommandDispatcher IRDispatcher; -#if defined(USE_TINY_IR_RECEIVER) -#include "TinyIRReceiver.hpp" // included in "IRremote" library - #if defined(LOCAL_INFO) #define CD_INFO_PRINT(...) Serial.print(__VA_ARGS__); #define CD_INFO_PRINTLN(...) Serial.println(__VA_ARGS__); @@ -68,6 +65,10 @@ IRCommandDispatcher IRDispatcher; #define CD_INFO_PRINTLN(...) void(); #endif +#if defined(USE_TINY_IR_RECEIVER) +#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. +#include "TinyIRReceiver.hpp" // included in "IRremote" library + void IRCommandDispatcher::init() { initPCIInterruptForTinyReceiver(); } @@ -76,25 +77,20 @@ void IRCommandDispatcher::init() { * This is the TinyReceiver callback function, which is called if a complete command was received * It checks for right address and then call the dispatcher */ -#if defined(ESP8266) || defined(ESP32) +# if defined(ESP8266) || defined(ESP32) IRAM_ATTR -#endif -void handleReceivedTinyIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) { - IRDispatcher.IRReceivedData.address = aAddress; - IRDispatcher.IRReceivedData.command = aCommand; - IRDispatcher.IRReceivedData.isRepeat = aFlags & IRDATA_FLAGS_IS_REPEAT; +# endif +void handleReceivedTinyIRData() { + IRDispatcher.IRReceivedData.address = TinyIRReceiverData.Address; + IRDispatcher.IRReceivedData.command = TinyIRReceiverData.Command; + IRDispatcher.IRReceivedData.isRepeat = TinyIRReceiverData.Flags & IRDATA_FLAGS_IS_REPEAT; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); - CD_INFO_PRINT(F("A=0x")); - CD_INFO_PRINT(aAddress, HEX); - CD_INFO_PRINT(F(" C=0x")); - CD_INFO_PRINT(aCommand, HEX); - if (IRDispatcher.IRReceivedData.isRepeat) { - CD_INFO_PRINT(F("R")); - } - CD_INFO_PRINTLN(); +# if defined(LOCAL_INFO) + printTinyReceiverResultMinimal(&Serial); +# endif - if (aAddress == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h + if (TinyIRReceiverData.Address == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h IRDispatcher.IRReceivedData.isAvailable = true; if(!IRDispatcher.doNotUseDispatcher) { /* @@ -212,7 +208,7 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate if (tIsNonBlockingCommand) { // short command here, just call CD_INFO_PRINT(F("Run non blocking command: ")); - CD_INFO_PRINTLN (tCommandName); + CD_INFO_PRINTLN(tCommandName); IRMapping[i].CommandToCall(); } else { if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) { @@ -226,7 +222,7 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate * This call is blocking!!! */ CD_INFO_PRINT(F("Run blocking command: ")); - CD_INFO_PRINTLN (tCommandName); + CD_INFO_PRINTLN(tCommandName); IRMapping[i].CommandToCall(); #if defined(TRACE) @@ -240,7 +236,7 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate BlockingCommandToRunNext = IRReceivedData.command; requestToStopReceived = true; // to stop running command CD_INFO_PRINT(F("Requested stop and stored blocking command ")); - CD_INFO_PRINT (tCommandName); + CD_INFO_PRINT(tCommandName); CD_INFO_PRINTLN(F(" as next command to run.")); } } diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 678ac9696..88f72024d 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -49,32 +49,6 @@ #if defined(USE_TINY_IR_RECEIVER) //#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt. -/* - * Set sensible receive pin for different CPU's - */ -#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) -#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" -# if defined(ARDUINO_AVR_DIGISPARKPRO) -#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 -# else -#define IR_RECEIVE_PIN 0 // PCINT0 -# endif -# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) -#define IR_RECEIVE_PIN 10 -# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) -#define IR_RECEIVE_PIN 21 // INT0 -# elif defined(ESP8266) -#define IR_RECEIVE_PIN 14 // D5 -# elif defined(ESP32) -#define IR_RECEIVE_PIN 15 -# elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) -#define IR_RECEIVE_PIN 3 // GPIO15 Use pin 3 since pin 2|GPIO25 is connected to LED on Pi pico -# elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico -#define IR_RECEIVE_PIN 15 // to be compatible with the Arduino Nano RP2040 Connect (pin3) -# else -#define IR_RECEIVE_PIN 2 // INT0 -# endif - #elif defined(USE_IRMP_LIBRARY) /* * IRMP version diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index e2659dec5..be18a649c 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -271,7 +271,7 @@ void loop() { } } - // Check if the command was repeated for more than 1000 ms + // Check if repeats of the IR command was sent for more than 1000 ms if (detectLongPress(1000)) { Serial.print(F("Command 0x")); Serial.print(IrReceiver.decodedIRData.command, HEX); @@ -292,7 +292,9 @@ void loop() { unsigned long sMillisOfFirstReceive; bool sLongPressJustDetected; /** - * @return true once after the repeated command was received for longer than aLongPressDurationMillis milliseconds, false otherwise. + * True once we received the consecutive repeats for more than aLongPressDurationMillis milliseconds. + * The first frame, which is no repeat, is NOT counted for the duration! + * @return true once after the repeated IR command was received for longer than aLongPressDurationMillis milliseconds, false otherwise. */ bool detectLongPress(uint16_t aLongPressDurationMillis) { if (!sLongPressJustDetected && (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)) { diff --git a/pictures/IR_UnitTest_delay.bmp b/pictures/IR_UnitTest_delay.bmp new file mode 100644 index 0000000000000000000000000000000000000000..00e17dd49ff3839919e28b31eda87541ab707942 GIT binary patch literal 1200054 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 Date: Sun, 31 Dec 2023 23:53:49 +0100 Subject: [PATCH 018/133] Fixes #1194 --- README.md | 7 +- examples/AllProtocolsOnLCD/ADCUtils.h | 49 ++++++++++-- examples/AllProtocolsOnLCD/ADCUtils.hpp | 80 +++++++++---------- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 2 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/MicroGirs/PinDefinitionsAndMore.h | 2 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 2 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/SimpleSender/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 2 +- examples/TinySender/PinDefinitionsAndMore.h | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 2 +- src/IRremote.hpp | 2 +- src/IRremoteInt.h | 2 +- src/private/IRTimer.hpp | 52 +++++++++--- 28 files changed, 152 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index a19284ef2..c20b36443 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,10 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr     [![Button Contribute](https://img.shields.io/badge/Contribute-752a61?style=for-the-badge&logoColor=white&logo=GitHub)](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributing.md) +#### If you find this program useful, please give it a star. + +🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/Arduino-IRremote/Arduino-IRremote) + # Overview @@ -861,7 +865,8 @@ The IR signal is sampled at a **50 µs interval**. For a constant 525 &micr And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
-And since the receivers generated marks are longer or shorter than the spaces, we have introduced the [`MARK_EXCESS_MICROS` value](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library) +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#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**. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index c32658c62..462800558 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -112,6 +112,43 @@ #error "No temperature channel definitions specified for this AVR CPU" #endif +/* + * Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion) + * + * Default values are suitable for Li-ion batteries. + * We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC. + * But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt. + */ +#if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) +#define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby +#endif +#if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) +#define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt +#endif + +#if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) +#define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT +#endif +#if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) +#define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT +#endif +#if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT) +#define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5250 // + 5 % operation voltage +#endif +#if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT) +#define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5500 // +10 %. Max recommended operation voltage +#endif +#if !defined(VCC_CHECK_PERIOD_MILLIS) +#define VCC_CHECK_PERIOD_MILLIS 10000L // 10 seconds period of VCC checks +#endif +#if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) +#define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT +#endif + +#if !defined(VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT) +#define VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT 4300 +#endif + extern long sLastVCCCheckMillis; extern uint8_t sVCCTooLowCounter; @@ -150,11 +187,13 @@ float getCPUTemperatureSimple(void); float getCPUTemperature(void); float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated -bool isVCCTooLowMultipleTimes(); -void resetVCCTooLowMultipleTimes(); -bool isVCCTooLow(); -bool isVCCTooHigh(); -bool isVCCTooHighSimple(); +bool isVCCUSBPowered() ; +bool isVCCUndervoltageMultipleTimes(); +void resetCounterForVCCUndervoltageMultipleTimes(); +bool isVCCUndervoltage(); +bool isVCCEmergencyUndervoltage(); +bool isVCCOvervoltage(); +bool isVCCOvervoltageSimple(); #endif // defined(__AVR__) ... diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index c96ceb6a6..7e2ef216e 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -481,7 +481,7 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) { void readVCCVoltageSimple(void) { // use AVCC with (optional) external capacitor at AREF pin as reference float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); - sVCCVoltage = (1023 * 1.1 * 4) / tVCC; + sVCCVoltage = (1023 * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC; } /* @@ -540,33 +540,17 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM } /* - * Default values are suitable for Li-ion batteries. - * We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC. - * But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt. + * Return true if sVCCVoltageMillivolt is > 4.3 V */ -#if !defined(VCC_STOP_THRESHOLD_MILLIVOLT) -#define VCC_STOP_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby -#endif -#if !defined(VCC_EMERGENCY_STOP_MILLIVOLT) -#define VCC_EMERGENCY_STOP_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt -#endif -#if !defined(VCC_TOO_HIGH_STOP_MILLIVOLT) -#define VCC_TOO_HIGH_STOP_MILLIVOLT 5250 // + 5 % operation voltage -#endif -#if !defined(VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT) -#define VCC_TOO_HIGH_EMERGENCY_STOP_MILLIVOLT 5500 // +10 %. Max recommended operation voltage -#endif -#if !defined(VCC_CHECK_PERIOD_MILLIS) -#define VCC_CHECK_PERIOD_MILLIS 10000 // Period of VCC checks -#endif -#if !defined(VCC_CHECKS_TOO_LOW_BEFORE_STOP) -#define VCC_CHECKS_TOO_LOW_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_STOP_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_STOP_MILLIVOLT -#endif +bool isVCCUSBPowered() { + readVCCVoltageMillivolt(); + return (sVCCVoltageMillivolt > VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT); +} /* - * @ return true only once, when VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times voltage too low -> shutdown + * @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown */ -bool isVCCTooLowMultipleTimes() { +bool isVCCUndervoltageMultipleTimes() { /* * Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds */ @@ -580,33 +564,35 @@ bool isVCCTooLowMultipleTimes() { readVCCVoltageMillivolt(); # endif - if (sVCCTooLowCounter < VCC_CHECKS_TOO_LOW_BEFORE_STOP) { + if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) { /* * Do not check again if shutdown has happened */ - if (sVCCVoltageMillivolt > VCC_STOP_THRESHOLD_MILLIVOLT) { + if (sVCCVoltageMillivolt > VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) { sVCCTooLowCounter = 0; // reset counter } else { /* - * Voltage too low, wait VCC_CHECKS_TOO_LOW_BEFORE_STOP (6) times and then shut down. + * Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then shut down. */ - if (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT) { + if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) { // emergency shutdown - sVCCTooLowCounter = VCC_CHECKS_TOO_LOW_BEFORE_STOP; + sVCCTooLowCounter = VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP; # if defined(INFO) - Serial.println(F("Voltage < " STR(VCC_EMERGENCY_STOP_MILLIVOLT) " mV detected -> emergency shutdown")); + Serial.println( + F( + "Voltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown")); # endif } else { sVCCTooLowCounter++; # if defined(INFO) - Serial.print(F("Voltage < " STR(VCC_STOP_THRESHOLD_MILLIVOLT) " mV detected: ")); - Serial.print(VCC_CHECKS_TOO_LOW_BEFORE_STOP - sVCCTooLowCounter); + Serial.print(F("Voltage < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected: ")); + Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter); Serial.println(F(" tries left")); # endif } - if (sVCCTooLowCounter == VCC_CHECKS_TOO_LOW_BEFORE_STOP) { + if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) { /* - * 6 times voltage too low -> shutdown + * 6 times voltage too low -> return signal for shutdown etc. */ return true; } @@ -616,14 +602,24 @@ bool isVCCTooLowMultipleTimes() { return false; } + /* - * Return true if VCC_EMERGENCY_STOP_MILLIVOLT (3 V) reached + * Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached */ -bool isVCCTooLow() { - return (sVCCVoltageMillivolt < VCC_EMERGENCY_STOP_MILLIVOLT); +bool isVCCUndervoltage() { + readVCCVoltageMillivolt(); + return (sVCCVoltageMillivolt < VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT); +} + +/* + * Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached + */ +bool isVCCEmergencyUndervoltage() { + readVCCVoltageMillivolt(); + return (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT); } -void resetVCCTooLowMultipleTimes() { +void resetCounterForVCCUndervoltageMultipleTimes() { sVCCTooLowCounter = 0; } @@ -636,13 +632,13 @@ void resetVCCTooLowMultipleTimes() { * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). * @return true if 5 % overvoltage reached */ -bool isVCCTooHigh() { +bool isVCCOvervoltage() { readVCCVoltageMillivolt(); - return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); + return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT); } -bool isVCCTooHighSimple() { +bool isVCCOvervoltageSimple() { readVCCVoltageMillivoltSimple(); - return (sVCCVoltageMillivolt > VCC_TOO_HIGH_STOP_MILLIVOLT); + return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT); } /* diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index e7ce194a7..b3099eb5f 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -322,7 +322,7 @@ void noTone(uint8_t aPinNumber){ #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) -#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warning in IRTimer.hpp +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif diff --git a/src/IRremote.hpp b/src/IRremote.hpp index f3e2919da..6f8bcf526 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -192,7 +192,7 @@ #if (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) # if !defined(SEND_PWM_BY_TIMER) #define SEND_PWM_BY_TIMER // the best and default method for ESP32 etc. -#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default. If this is not intended, deactivate the line in IRremote.hpp over this warning message in file IRremote.hpp. +#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default, since we have the resources and timing is more exact than the software generated one. If this is not intended, deactivate the line in IRremote.hpp over this warning message in file IRremote.hpp. # endif #else # if defined(SEND_PWM_BY_TIMER) diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 10d87de8e..a12a9f663 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -417,7 +417,7 @@ class IRsend { IRsend(); /* - * IR_SEND_PIN is defined + * IR_SEND_PIN is defined or fixed by timer, value of IR_SEND_PIN is then "DeterminedByTimer" */ #if defined(IR_SEND_PIN) void begin(); diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index b47d733aa..d7acb48fe 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -52,12 +52,13 @@ void enableSendPWMByTimer(); void disableSendPWMByTimer(); void timerConfigForSend(uint16_t aFrequencyKHz); -#if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) ) -#define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation are independent, so it is recommended to always define SEND_PWM_BY_TIMER +// SEND_PWM_BY_TIMER is defined in IRremote.hpp line 195. +#if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) ) +#define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here. #endif -#if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For e.g ESP32 IR_SEND_PIN definition is useful -#undef IR_SEND_PIN // avoid warning below, user warning is done at IRremote.hpp +#if defined(IR_SEND_PIN) && defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER) // For ESP32 etc. IR_SEND_PIN definition is useful +#undef IR_SEND_PIN // To avoid "warning: "IR_SEND_PIN" redefined". The user warning is done at IRremote.hpp line 202. #endif // Macros for enabling timers for development @@ -1434,8 +1435,7 @@ void timerConfigForReceive() { // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() - -# if !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL) +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL) #define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif @@ -1481,24 +1481,52 @@ void timerConfigForReceive() { // every 50 us, autoreload = true } +# if !defined(IR_SEND_PIN) +uint8_t sLastSendPin = 0; // To detach before attach, if already attached +# endif + # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution +# else + ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API +# endif } void disableSendPWMByTimer() { +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0); +# else + ledcWrite(IrSender.sendPin, 0); // New API +# endif } /* - * timerConfigForSend() is used exclusively by IRsend::enableIROut() - * ledcWrite since ESP 2.0.2 does not work if pin mode is set. Disable receive interrupt if it uses the same resource + * timerConfigForSend() is used exclusively by IRsend::enableIROut() (or enableHighFrequencyIROut()) + * ledcWrite since ESP 2.0.2 does not work if pin mode is set. */ void timerConfigForSend(uint16_t aFrequencyKHz) { +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution -# if defined(IR_SEND_PIN) - ledcAttachPin(IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // bind pin to channel -# else - ledcAttachPin(IrSender.sendPin, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // bind pin to channel +# if defined(IR_SEND_PIN) + ledcAttachPin(IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // attach pin to channel +# else + if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ + ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194 + } + ledcAttachPin(IrSender.sendPin, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // attach pin to channel + sLastSendPin = IrSender.sendPin; +# endif +# else // New API here +# if defined(IR_SEND_PIN) + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // New API +# else + if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ + ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 + } + ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // New API + sLastSendPin = IrSender.sendPin; +# endif # endif } # endif // defined(SEND_PWM_BY_TIMER) From 36403d810b73f2202b2f4ba08d0cee07298c2b5d Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 8 Jan 2024 11:52:29 +0100 Subject: [PATCH 019/133] TinyIR --- .github/workflows/LibraryBuild.yml | 42 +++++++++---------- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 8 ++-- examples/ControlRelay/PinDefinitionsAndMore.h | 8 ++-- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 8 ++-- .../PinDefinitionsAndMore.h | 8 ++-- examples/MicroGirs/PinDefinitionsAndMore.h | 8 ++-- .../ReceiveAndSend/PinDefinitionsAndMore.h | 8 ++-- .../PinDefinitionsAndMore.h | 8 ++-- examples/ReceiveDemo/PinDefinitionsAndMore.h | 8 ++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 8 ++-- .../PinDefinitionsAndMore.h | 8 ++-- .../SendAndReceive/PinDefinitionsAndMore.h | 8 ++-- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 8 ++-- examples/SendDemo/PinDefinitionsAndMore.h | 8 ++-- .../PinDefinitionsAndMore.h | 8 ++-- .../SendProntoDemo/PinDefinitionsAndMore.h | 8 ++-- examples/SendRawDemo/PinDefinitionsAndMore.h | 8 ++-- .../SimpleReceiver/PinDefinitionsAndMore.h | 8 ++-- .../PinDefinitionsAndMore.h | 8 ++-- examples/SimpleSender/PinDefinitionsAndMore.h | 8 ++-- examples/TinyReceiver/PinDefinitionsAndMore.h | 8 ++-- examples/TinySender/PinDefinitionsAndMore.h | 8 ++-- examples/TinySender/TinySender.ino | 4 +- examples/UnitTest/PinDefinitionsAndMore.h | 8 ++-- src/TinyIRSender.hpp | 4 ++ 25 files changed, 115 insertions(+), 111 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 734432f14..908dec28a 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -60,9 +60,9 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect -# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll -# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled -# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll + - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro # - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 @@ -193,26 +193,26 @@ jobs: # # 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:attinyx5micr:LTO=enable,sketchclock=16pll + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER -# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled -# platform-url: http://drazzy.com/package_drazzy.com_index.json -# required-libraries: ATtinySerialOut -# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino -# build-properties: # the flags were put in compiler.cpp.extra_flags -# SimpleSender: -DSEND_PWM_BY_TIMER + - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER -# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz -# platform-url: http://drazzy.com/package_drazzy.com_index.json -# required-libraries: ATtinySerialOut -# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino -# build-properties: # the flags were put in compiler.cpp.extra_flags -# SimpleSender: -DSEND_PWM_BY_TIMER + - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + platform-url: http://drazzy.com/package_drazzy.com_index.json + required-libraries: ATtinySerialOut + sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino + build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER # # MegaCore diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 970d00267..6d8ff8af6 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -44,6 +44,8 @@ */ #include +#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's + //#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. @@ -52,8 +54,6 @@ #include "TinyIRSender.hpp" -#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's - void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index b3099eb5f..54395f68e 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -90,14 +90,14 @@ # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore // Tiny Core Dev board -// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ -// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ -#define IR_RECEIVE_PIN PIN_PA1 // use 18 for TinyCore32 +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 19 #define TONE_PIN PIN_PA3 // 20 #define APPLICATION_PIN PIN_PA0 // 0 #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output -#define LED_BUILTIN PIN_PA6 // use 2 for TinyCore32 +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 0672383bb..03d0b9334 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -60,6 +60,10 @@ * @{ */ +#if !defined(IR_SEND_PIN) +#warning "IR_SEND_PIN is not defined, so it is set to 3" +#define IR_SEND_PIN 3 +#endif /* * Generate 38 kHz IR signal by bit banging */ From ea28282d1c88b69d01297ee9ce4396825a818144 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 19 Jan 2024 20:39:19 +0100 Subject: [PATCH 020/133] Flipper Zero --- README.md | 25 ++++++-- examples/AllProtocolsOnLCD/ADCUtils.h | 9 ++- examples/AllProtocolsOnLCD/ADCUtils.hpp | 6 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 57 +++++++++++-------- src/ir_Kaseikyo.hpp | 7 ++- src/ir_Samsung.hpp | 15 ++++- 6 files changed, 79 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index c20b36443..abed722a3 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,16 @@ If `IR_SEND_PIN` is specified (as constant), it reduces program size and improve ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html +### Flipper Zero +[Flipper IRDB Database](https://github.com/Lucaslhm/Flipper-IRDB) + +| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) | +|-|-| +| Samsung32 | Samsung | +| NEC | NEC | +| NECext | ONKYO | +| [\\\\\\\\\](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)
and ID is MSB of address.
address: 8A 02 20 00
command: 56 03 00 00
-> **IRremote:**
Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \\\\\\\ | +
@@ -763,15 +773,18 @@ If you can provide **examples of using a periodic timer for interrupts** for the
# Timer and pin usage -The **receiver sample interval of 50 µs is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used.
-Every pin can be used for receiving. +The **receiver sample interval of 50 µs is generated by a timer**. On many boards this must be a hardware timer. On some boards where a software timer is available, the software timer is used. + +Every pin can be used for receiving.
+If software PWM is selected, which is default, every pin can also be used for sending. Sending with software PWM does not require a timer! The TinyReceiver example uses the **TinyReceiver** library, which can **only receive NEC codes, but does not require any timer** and runs even on a 1 MHz ATtiny85. -The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). It can be adjusted here.
+The code for the timer and the **timer selection** is located in [private/IRTimer.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/private/IRTimer.hpp). The selected timer can be adjusted here. + **Be aware that the hardware timer used for receiving should not be used for analogWrite()!**.
-| Board/CPU | Receive
& PWM Timers| Hardware-PWM Pin | analogWrite()
pins occupied by timer | +| Board/CPU | Receive
& send PWM Timer
Default timer is **bold** | Hardware-Send-PWM Pin | analogWrite()
pins occupied by timer | |-|-|-|-| | [ATtiny84](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x4.md) | **1** | **6** | | | [ATtiny85 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x5.md) | **0**, 1 | **0**, 4 | **0**, 1 & 4 | @@ -787,9 +800,9 @@ The code for the timer and the **timer selection** is located in [private/IRTime | [ATmega64, ATmega128, ATmega1281, ATmega2561](https://github.com/MCUdude/MegaCore#supported-microcontrollers) | **1** | **13** | | [ATmega8515, ATmega162](https://github.com/MCUdude/MajorCore#pinout ) | **1** | **13** | | ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** | -| ATmega1280, ATmega2560 | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | | +| ATmega1280, **ATmega2560** | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | 5, 6, **9**, 11, 46 | | ATmega4809 | **TCB0** | **A4** | | -| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | | +| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 | | Zero (SAMD) | **TC3** | \*, **9** | | | [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | | | [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | | diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 462800558..d677fd36f 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -145,8 +145,13 @@ #define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT #endif -#if !defined(VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT) -#define VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT 4300 +#if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT) +#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4300 // Assume USB powered above this voltage +#endif + +#if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) +#define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT 4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN. +// In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply #endif extern long sLastVCCCheckMillis; diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 7e2ef216e..19744a8c5 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -540,11 +540,12 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM } /* - * Return true if sVCCVoltageMillivolt is > 4.3 V + * Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V */ bool isVCCUSBPowered() { readVCCVoltageMillivolt(); - return (sVCCVoltageMillivolt > VOLTAGE_USB_LOWER_THRESHOLD_MILLIVOLT); + return (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT < sVCCVoltageMillivolt + && sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT); } /* @@ -602,7 +603,6 @@ bool isVCCUndervoltageMultipleTimes() { return false; } - /* * Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached */ diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 5aeeb13d9..6daddec6c 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -105,7 +105,8 @@ uint32_t sMillisOfLastReceivedIRFrame = 0; #if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD) #define USE_LCD # if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) -// For cyclically display of VCC +// For cyclically display of VCC and isVCCUSBPowered() +#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4250 #include "ADCUtils.hpp" #define MILLIS_BETWEEN_VOLTAGE_PRINT 5000 #define LCD_VOLTAGE_START_INDEX 11 @@ -114,13 +115,12 @@ bool ProtocolStringOverwritesVoltage = false; # endif #define LCD_IR_COMMAND_START_INDEX 9 -#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD) - +void printsVCCVoltageMillivoltOnLCD(); void printIRResultOnLCD(); size_t printByteHexOnLCD(uint16_t aHexByteValue); void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint); -uint16_t sVCCMillivolt; +#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD) void setup() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. @@ -180,8 +180,8 @@ void setup() { Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding")); #endif -#if defined(USE_LCD) && defined(__AVR__) && defined(ADCSRA) && defined(ADATE) - getVCCVoltageMillivoltSimple(); // to initialize ADC mux and reference +#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) + readVCCVoltageMillivolt(); #endif #if defined(USE_SERIAL_LCD) @@ -201,7 +201,7 @@ void setup() { #endif #if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) - sVCCMillivolt = getVCCVoltageMillivoltSimple(); + readVCCVoltageMillivolt(); #endif } @@ -236,10 +236,10 @@ void loop() { if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) #if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) - && sVCCMillivolt > 4222 + || isVCCUSBPowered() #endif - ) { - // Print more info, but only if we are connected to USB, i.e. VCC is > 4222 mV, because this may take to long to detect some fast repeats + ) { + // Print more info, but only if we are connected to USB, i.e. VCC is > 4300 mV, because this may take to long to detect some fast repeats IrReceiver.printIRSendUsage(&Serial); IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-) } @@ -266,10 +266,17 @@ void loop() { } // if (IrReceiver.decode()) /* - * Check for attention every 10 minute, after the current measurement was finished + * Check if generating attention beep every minute, after the current measurement was finished */ - if (millis() - sMillisOfLastReceivedIRFrame >= MILLIS_BETWEEN_ATTENTION_BEEP) { + if ((millis() - sMillisOfLastReceivedIRFrame) >= MILLIS_BETWEEN_ATTENTION_BEEP +#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) + && !isVCCUSBPowered() +#endif + ) { sMillisOfLastReceivedIRFrame = millis(); +#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) + printsVCCVoltageMillivoltOnLCD(); +#endif IrReceiver.stop(); tone(TONE_PIN, 2200); delay(50); @@ -284,18 +291,25 @@ void loop() { * Periodically print VCC */ sMillisOfLastVoltagePrint = millis(); - sVCCMillivolt = getVCCVoltageMillivoltSimple(); - char tVoltageString[5]; - dtostrf(sVCCMillivolt / 1000.0, 4, 2, tVoltageString); - myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0); - myLCD.print(' '); - myLCD.print(tVoltageString); - myLCD.print('V'); + readVCCVoltageMillivolt(); + printsVCCVoltageMillivoltOnLCD(); } #endif } +#if defined(USE_LCD) +void printsVCCVoltageMillivoltOnLCD() { +# if defined(ADC_UTILS_ARE_AVAILABLE) + char tVoltageString[5]; + dtostrf(sVCCVoltageMillivolt / 1000.0, 4, 2, tVoltageString); + myLCD.setCursor(LCD_VOLTAGE_START_INDEX - 1, 0); + myLCD.print(' '); + myLCD.print(tVoltageString); + myLCD.print('V'); +# endif +} + /* * LCD output for 1602 LCDs * 40 - 55 Milliseconds per initial output @@ -305,7 +319,6 @@ void loop() { * */ void printIRResultOnLCD() { -#if defined(USE_LCD) static uint16_t sLastProtocolIndex = 4711; static uint16_t sLastProtocolAddress = 4711; static uint16_t sLastCommand = 0; @@ -421,10 +434,8 @@ void printIRResultOnLCD() { myLCD.print(' '); } } // IrReceiver.decodedIRData.protocol == UNKNOWN -#endif // defined(USE_LCD) } -#if defined(USE_LCD) size_t printByteHexOnLCD(uint16_t aHexByteValue) { myLCD.print(F("0x")); size_t tPrintSize = 2; @@ -440,4 +451,4 @@ void printSpacesOnLCD(uint_fast8_t aNumberOfSpacesToPrint) { myLCD.print(' '); } } -#endif +#endif // defined(USE_LCD) diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 4c1b9b8d9..90fe1ece9 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -87,9 +87,10 @@ // 01000000 00100100 0110Dev_ Sub_Dev_ Fun____ XOR( B2, B3, B4) - Byte 0,1 and vendor parity showing Panasonic vendor code 0x2002. // 1. interpretation: // see: http://www.remotecentral.com/cgi-bin/mboard/rc-pronto/thread.cgi?26152 -// 2. interpretation: +// 2. interpretation (Flipper Zero style): // see: https://www.mikrocontroller.net/articles/IRMP_-_english#KASEIKYO -// Implemented is: +// Implemented is Samsung style: +// which is derived from Samsung remotes and may not be optimal for Denon kind of Kaseikyo protokol usage. // #define KASEIKYO_VENDOR_ID_BITS 16 #define KASEIKYO_VENDOR_ID_PARITY_BITS 4 @@ -126,7 +127,7 @@ KASEIKYO_HEADER_SPACE, KASEIKYO_BIT_MARK, KASEIKYO_ONE_SPACE, KASEIKYO_BIT_MARK, ************************************/ /** - * Address can be interpreted as sub-device << 8 + device + * Address can be interpreted as sub-device << 4 + 4 bit device */ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aVendorCode) { // Set IR carrier frequency diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index c61590633..f2c256ae0 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -72,6 +72,10 @@ // https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG48 // LSB first, 1 start bit + 16 bit address + 16 or 32 bit data + 1 stop bit. // Here https://forum.arduino.cc/t/klimaanlage-per-ir-steuern/1051381/10 the address (0xB24D) is also 8 bits and then 8 inverted bits +// +// Here https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 +// Address is 8 bit + same 8 bit if data is 8 bit and ~8 bit. +// // IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,1,^110)+ ==> 8 bit + 8 bit inverted data - Samsung32 // IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:16,1,^110)+ ==> 16 bit data - still Samsung32 // IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,G:8,~G:8,1,^110)+ ==> 2 x (8 bit + 8 bit inverted data) - Samsung48 @@ -84,7 +88,7 @@ // except SAMSUNG_HEADER_MARK, values are like NEC #define SAMSUNG_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0 -#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4500 | 180 +#define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4500 | 180 periods #define SAMSUNG_HEADER_SPACE (8 * SAMSUNG_UNIT) // 4500 #define SAMSUNG_BIT_MARK SAMSUNG_UNIT #define SAMSUNG_ONE_SPACE (3 * SAMSUNG_UNIT) // 1690 | 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0 @@ -93,8 +97,7 @@ #define SAMSUNG_AVERAGE_DURATION 55000 // SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones #define SAMSUNG_REPEAT_DURATION (SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + SAMSUNG_BIT_MARK + SAMSUNG_ZERO_SPACE + SAMSUNG_BIT_MARK) #define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down. -#define SAMSUNG_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD - SAMSUNG_AVERAGE_DURATION) -#define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_DISTANCE + (SAMSUNG_REPEAT_DISTANCE / 4)) // Just a guess +#define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, @@ -165,6 +168,12 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb // Send 8 command bits and then 8 inverted command bits LSB first tSendValue.UBytes[2] = aCommand; tSendValue.UBytes[3] = ~aCommand; + if (aAddress < 0x100) { + // This makes it flipper IRDB compatible + // https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 + // Duplicate address byte, if data is 8 bit and 8 bit inverted and address is 8bit + tSendValue.UBytes[1] = aAddress; + } } else { // Send 16 command bits tSendValue.UWords[1] = aCommand; From fbd35659413cd667154fed5a7ba64edca5acfa23 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 22 Jan 2024 22:15:08 +0100 Subject: [PATCH 021/133] Documentation --- examples/ReceiveDump/ReceiveDump.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 23b9b5759..4accf67ea 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -86,7 +86,7 @@ void setup() { Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed")); Serial.print(MARK_EXCESS_MICROS); Serial.println(); - Serial.println(F("Because of the verbose output (>200 ms at 115200), repeats are probably not dumped correctly!")); + Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!")); Serial.println(); } @@ -122,6 +122,9 @@ void loop() { Serial.println(MARK_EXCESS_MICROS); IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables + Serial.println(); // blank line between entries + IrReceiver.printIRSendUsage(&Serial); + Serial.println(); // blank line between entries IrReceiver.compensateAndPrintIRResultAsPronto(&Serial); From a7bd9ea78bf71458c6cd73b87bb3f541216649e6 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 23 Jan 2024 15:59:24 +0100 Subject: [PATCH 022/133] Bumped version to 4.2.1 --- changelog.md | 3 +++ library.json | 2 +- library.properties | 4 ++-- src/IRVersion.h | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/changelog.md b/changelog.md index 9236e5ceb..2bf36f7ab 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,9 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - New TinyIRReceiverData which is filled with address, command and flags. - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated. +- Fix changing IR_SEND_PIN dynamically for ESP32. +- Fix wrong type of tEnableLEDFeedback. +- Support for ESP32-C3. # 4.2.0 - The old decode function is renamed to decode_old(decode_results *aResults). decode (decode_results *aResults) is only available in IRremote.h and prints a message. diff --git a/library.json b/library.json index e264f4c88..611a73487 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/z3t0/Arduino-IRremote.git" }, - "version": "4.2.0", + "version": "4.2.1", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index 75ad868d0..b4a21a1ad 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.2.0 +version=4.2.1 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.

New: Added untested Uno R4 support. Improved ESP support. Added DECODE_ONKYO. Old decode() prints a message now.
Release notes
+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. NEW: TinyReceiver 2.0 and minor fixes. 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/src/IRVersion.h b/src/IRVersion.h index 06cd4d40c..4750c6a43 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.2.0" +#define VERSION_IRREMOTE "4.2.1" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 2 -#define VERSION_IRREMOTE_PATCH 0 +#define VERSION_IRREMOTE_PATCH 1 /* * Macro to convert 3 version parts into an integer From 11ec335b357ef2a8c00f439cfc7ebfd178cb8cf5 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 24 Jan 2024 17:32:29 +0100 Subject: [PATCH 023/133] closes #1196 --- README.md | 6 +++--- examples/SendBoseWaveDemo/SendBoseWaveDemo.ino | 8 ++++++-- examples/SendDemo/SendDemo.ino | 10 ++++++++-- examples/UnitTest/UnitTest.ino | 10 ++++++++-- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index abed722a3..172326bc6 100644 --- a/README.md +++ b/README.md @@ -399,12 +399,12 @@ The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957 ## Send pin Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active. -If `IR_SEND_PIN` is specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this macro. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library). +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#compile-options--macros-for-this-library). ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html -### Flipper Zero +## Flipper Zero [Flipper IRDB Database](https://github.com/Lucaslhm/Flipper-IRDB) | [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) | @@ -696,7 +696,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | -| `IR_SEND_PIN` | disabled | If specified (as constant), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | +| `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#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 054c083c1..60197cc2f 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -114,8 +114,12 @@ void setup() { IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); #else - IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin - Serial.println(F("Send IR signals at pin 3")); + uint8_t tSendPin = 3; + IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin + // You can change send pin later with IrSender.setSendPin(); + + Serial.print(F("Send IR signals at pin ")); + Serial.println(tSendPin); #endif sPrintMenu = true; diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index e6bd7d0cf..27dc4696e 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -42,6 +42,7 @@ //#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory //#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! +//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below #include #define DELAY_AFTER_SEND 2000 @@ -64,8 +65,13 @@ void setup() { Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); # endif #else - IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin - Serial.println(F("Send IR signals at pin 3")); + // Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN + uint8_t tSendPin = 3; + IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin + // You can change send pin later with IrSender.setSendPin(); + + Serial.print(F("Send IR signals at pin ")); + Serial.println(tSendPin); #endif #if !defined(SEND_PWM_BY_TIMER) diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index de76e93c3..0402448b4 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -93,6 +93,7 @@ #define DECODE_FAST #endif +//#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below #include #if defined(APPLICATION_PIN) @@ -144,8 +145,13 @@ void setup() { Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); # endif #else - IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin - Serial.println(F("Send IR signals at pin 3")); + // Here the macro IR_SEND_PIN is not defined or undefined above with #undef IR_SEND_PIN + uint8_t tSendPin = 3; + IrSender.begin(tSendPin, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin + // You can change send pin later with IrSender.setSendPin(); + + Serial.print(F("Send IR signals at pin ")); + Serial.println(tSendPin); #endif #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604 From 7131adf71eb8472b0a81730c2a43dac2af857b83 Mon Sep 17 00:00:00 2001 From: Buzzerb <33309634+Buzzerb@users.noreply.github.com> Date: Wed, 14 Feb 2024 01:11:11 +1100 Subject: [PATCH 024/133] Added Extended NEC Protocol to TinyIR (#1200) Added the option to receive Extended NEC using TinyIRReceiver with a USE_EXTENDED_NEC_PROTOCOL compile option. Tested working on an Uno R3. Functions similarly to the USE_ONKYO_PROTOCOL flag, mostly reusing its code. Documentation and example file TinyReceiver.ino updated to match. --- README.md | 7 ++++--- examples/TinyReceiver/TinyReceiver.ino | 3 ++- src/TinyIR.h | 2 ++ src/TinyIRReceiver.hpp | 6 ++++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 172326bc6..9ed35c9e8 100644 --- a/README.md +++ b/README.md @@ -418,7 +418,7 @@ http://www.harctoolbox.org/IR-resources.html # Tiny NEC receiver and sender -For applications only requiring NEC or FAST -see below- protocol, there is a special receiver / sender included,
+For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
which has very **small code size of 500 bytes and does NOT require any timer**. Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote#irdispatcherdemo) examples.
@@ -598,7 +598,7 @@ A simple example can be tested online with [WOKWI](https://wokwi.com/projects/33 #### TinyReceiver + TinySender If **code size** or **timer usage** matters, look at these examples.
-The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
+The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
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**.
@@ -717,7 +717,8 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. | | `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. | -| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | +| `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 both 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. | diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 9ded911f1..81604dd43 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -59,7 +59,8 @@ * Set compile options to modify the generated code. */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. -//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. diff --git a/src/TinyIR.h b/src/TinyIR.h index c274b936e..bfcff36af 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -134,6 +134,8 @@ #define TINY_RECEIVER_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity # if defined(USE_ONKYO_PROTOCOL) #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity +# elif defined(USE_EXTENDED_NEC_PROTOCOL) +#define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity # else #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity # endif diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index f81d71cf2..19f692707 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -58,7 +58,8 @@ * - 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_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_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 both 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. @@ -76,7 +77,8 @@ #endif //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. -//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. From 8b9e036889a264d6cc7ea04fa91fcdb9cdd48910 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 13 Feb 2024 15:46:48 +0100 Subject: [PATCH 025/133] Convenience function isIRReceiverAttachedForTinyReceiver() and 3.party --- Doxyfile | 2 +- README.md | 8 +- changelog.md | 4 + examples/AllProtocolsOnLCD/ADCUtils.h | 14 ++- examples/AllProtocolsOnLCD/ADCUtils.hpp | 103 ++++++++++++++++-- .../IRDispatcherDemo/IRCommandDispatcher.h | 28 +++-- .../IRDispatcherDemo/IRCommandDispatcher.hpp | 77 ++++++++++--- examples/TinyReceiver/TinyReceiver.ino | 2 +- src/TinyIR.h | 1 + src/TinyIRReceiver.hpp | 15 ++- 10 files changed, 215 insertions(+), 39 deletions(-) diff --git a/Doxyfile b/Doxyfile index 0ce0d4bf5..a879240e6 100644 --- a/Doxyfile +++ b/Doxyfile @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = ..\Arduino-IRremote_gh-pages +OUTPUT_DIRECTORY = E:\WORKSPACE_ARDUINO\lib\Arduino-IRremote_gh-pages # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and diff --git a/README.md b/README.md index 9ed35c9e8..3c7847a87 100644 --- a/README.md +++ b/README.md @@ -598,7 +598,9 @@ A simple example can be tested online with [WOKWI](https://wokwi.com/projects/33 #### TinyReceiver + TinySender If **code size** or **timer usage** matters, look at these examples.
-The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**. They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
+The **[TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinyReceiver/TinyReceiver.ino)** example uses the **TinyIRReceiver** library +which can **only receive NEC, Extended NEC, ONKYO and FAST protocols, but does not require any timer**. +They use pin change interrupt for on the fly decoding, which is the reason for the restricted protocol choice.
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**.
@@ -718,13 +720,15 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED function. Saves 14 bytes program memory. | | `DISABLE_PARITY_CHECKS` | disabled | Disables the addres and command parity checks. Saves 48 bytes program memory. | | `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | -| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | +| `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | | `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. | | `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. | | `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. | The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. +| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) for receiving IR codes. | | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | +| `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | ### Changing include (*.h) files with Arduino IDE First, use *Sketch > Show Sketch Folder (Ctrl+K)*.
diff --git a/changelog.md b/changelog.md index 2bf36f7ab..0f1f2e934 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.2.2 +- Added convenience function isIRReceiverAttachedForTinyReceiver(). +- Added Extended NEC Protocol to TinyIR by Butzerb + # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. - TinyReceiver 2.0 diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index d677fd36f..ce283c2f3 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -85,6 +85,7 @@ #define ADC_TEMPERATURE_CHANNEL_MUX 15 #define ADC_1_1_VOLT_CHANNEL_MUX 12 #define ADC_GND_CHANNEL_MUX 13 +#define ADC_CHANNEL_MUX_MASK 0x0F #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) #define ADC_ISCR_CHANNEL_MUX 3 @@ -92,20 +93,25 @@ #define ADC_1_1_VOLT_CHANNEL_MUX 12 #define ADC_GND_CHANNEL_MUX 14 #define ADC_VCC_4TH_CHANNEL_MUX 13 +#define ADC_CHANNEL_MUX_MASK 0x1F #elif defined(__AVR_ATmega328P__) #define ADC_TEMPERATURE_CHANNEL_MUX 8 #define ADC_1_1_VOLT_CHANNEL_MUX 14 #define ADC_GND_CHANNEL_MUX 15 +#define ADC_CHANNEL_MUX_MASK 0x0F #elif defined(__AVR_ATmega32U4__) #define ADC_TEMPERATURE_CHANNEL_MUX 0x27 #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E #define ADC_GND_CHANNEL_MUX 0x1F +#define ADC_CHANNEL_MUX_MASK 0x3F #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E #define ADC_GND_CHANNEL_MUX 0x1F +#define ADC_CHANNEL_MUX_MASK 0x1F + #define INTERNAL INTERNAL1V1 #else @@ -164,7 +170,10 @@ uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t a uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent); void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference); uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); -uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); +uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples); +uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); +uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale, + uint16_t aNumberOfSamples); uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples); uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire); uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay, @@ -192,7 +201,8 @@ float getCPUTemperatureSimple(void); float getCPUTemperature(void); float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated -bool isVCCUSBPowered() ; +bool isVCCUSBPowered(); +bool isVCCUSBPowered(Print *aSerial); bool isVCCUndervoltageMultipleTimes(); void resetCounterForVCCUndervoltageMultipleTimes(); bool isVCCUndervoltage(); diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 19744a8c5..0cff66eb7 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -58,7 +58,7 @@ 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) +#if defined(DEBUG) && !defined(LOCAL_DEBUG) #define LOCAL_DEBUG #else //#define LOCAL_DEBUG // This enables debug output only for this file @@ -161,12 +161,15 @@ uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, ui if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) { #else if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) { +#endif +#if defined(LOCAL_DEBUG) + Serial.println(F("Switch from DEFAULT to INTERNAL")); #endif /* * Switch reference from DEFAULT to INTERNAL */ delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board - } else if ((tOldADMUX & 0x0F) != aADCChannelNumber) { + } else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK) != aADCChannelNumber) { if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) { /* * Internal 1.1 Volt channel requires <= 200 us for Nano board @@ -249,9 +252,10 @@ uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, ui /* * Returns sum of all sample values - * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE in ADCUtils.h. + * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h. + * @ param aNumberOfSamples If > 64 an overflow may occur. */ -uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) { +uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) { uint16_t tSumValue = 0; ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); @@ -275,6 +279,65 @@ uint16_t readADCChannelWithReferenceMultiSamples(uint8_t aADCChannelNumber, uint return tSumValue; } +/* + * Returns sum of all sample values + * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino for ADC_PRESCALE128 in ADCUtils.h. + * @ param aPrescale can be one of ADC_PRESCALE2, ADC_PRESCALE4, 8, 16, 32, 64, 128. + * ADC_PRESCALE32 is recommended for excellent linearity and fast readout of 26 microseconds + * @ param aNumberOfSamples If > 16k an overflow may occur. + */ +uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale, + uint16_t aNumberOfSamples) { + uint32_t tSumValue = 0; + ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); + + ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. + // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale); + + for (uint16_t i = 0; i < aNumberOfSamples; i++) { + /* + * wait for free running conversion to finish. + * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion. + */ + loop_until_bit_is_set(ADCSRA, ADIF); + + ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished + // Add value + tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here + // tSumValue += (ADCH << 8) | ADCL; // this does NOT work! + } + ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode) + return tSumValue; +} + +/* + * Returns sum of all sample values + * Assumes, that channel and reference are still set to the right values + * @ param aNumberOfSamples If > 16k an overflow may occur. + */ +uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples) { + uint32_t tSumValue = 0; + + ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1. + // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale); + + for (uint16_t i = 0; i < aNumberOfSamples; i++) { + /* + * wait for free running conversion to finish. + * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion. + */ + loop_until_bit_is_set(ADCSRA, ADIF); + + ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished + // Add value + tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here + // tSumValue += (ADCH << 8) | ADCL; // this does NOT work! + } + ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode) + return tSumValue; +} /* * use ADC_PRESCALE32 which gives 26 us conversion time and good linearity * @return the maximum value of aNumberOfSamples samples. @@ -408,7 +471,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 = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); + float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); return ((1023 * 1.1 * 4) / tVCC); } @@ -419,7 +482,7 @@ float getVCCVoltageSimple(void) { */ uint16_t getVCCVoltageMillivoltSimple(void) { // use AVCC with external capacitor at AREF pin as reference - uint16_t tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); + uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC); } @@ -459,6 +522,9 @@ uint16_t getVCCVoltageMillivolt(void) { return ((1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC); } +/* + * Does not set sVCCVoltageMillivolt + */ uint16_t printVCCVoltageMillivolt(Print *aSerial) { aSerial->print(F("VCC=")); uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt(); @@ -480,7 +546,7 @@ void readAndPrintVCCVoltageMillivolt(Print *aSerial) { */ void readVCCVoltageSimple(void) { // use AVCC with (optional) external capacitor at AREF pin as reference - float tVCC = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); + float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); sVCCVoltage = (1023 * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC; } @@ -491,7 +557,7 @@ void readVCCVoltageSimple(void) { */ void readVCCVoltageMillivoltSimple(void) { // use AVCC with external capacitor at AREF pin as reference - uint16_t tVCCVoltageMillivoltRaw = readADCChannelWithReferenceMultiSamples(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); + uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4); sVCCVoltageMillivolt = (1023L * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw; } @@ -548,6 +614,25 @@ bool isVCCUSBPowered() { && sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT); } +/* + * Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V + */ +bool isVCCUSBPowered(Print *aSerial) { + readVCCVoltageMillivolt(); + aSerial->print(F("USB powered is ")); + bool tReturnValue; + if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT + < sVCCVoltageMillivolt&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) { + tReturnValue = true; + aSerial->print(F("true ")); + } else { + tReturnValue = false; + aSerial->print(F("false ")); + } + printVCCVoltageMillivolt(aSerial); + return tReturnValue; +} + /* * @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown */ @@ -685,7 +770,7 @@ float getCPUTemperature(void) { } #else // defined(ADC_UTILS_ARE_AVAILABLE) -// Dummy definition of functions defined in ADCUtils to compile examples without errors +// Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors /* * Persistent storage for VCC value */ diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.h b/examples/IRDispatcherDemo/IRCommandDispatcher.h index e3f46127b..83a98b27c 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.h +++ b/examples/IRDispatcherDemo/IRCommandDispatcher.h @@ -5,14 +5,14 @@ * * To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" * - * Copyright (C) 2019-2021 Armin Joachimsmeyer + * Copyright (C) 2019-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * - * ServoEasing is free software: you can redistribute it and/or modify + * IRCommandDispatcher is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -38,6 +38,22 @@ #define IR_COMMAND_FLAG_REPEATABLE 0x01 // repeat accepted #define IR_COMMAND_FLAG_NON_BLOCKING 0x02 // Non blocking (short) command that can be processed any time and may interrupt other IR commands - used for stop, set direction etc. #define IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING (IR_COMMAND_FLAG_REPEATABLE | IR_COMMAND_FLAG_NON_BLOCKING) +#define IR_COMMAND_FLAG_BEEP 0x04 // Do a single short beep before executing command. May not be useful for short or repeating commands. +#define IR_COMMAND_FLAG_BLOCKING_BEEP (IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP) + + +#if !defined(IS_STOP_REQUESTED) +#define IS_STOP_REQUESTED IRDispatcher.requestToStopReceived +#endif +#if !defined(RETURN_IF_STOP) +#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return +#endif +#if !defined(BREAK_IF_STOP) +#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break +#endif +#if !defined(DELAY_AND_RETURN_IF_STOP) +#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return +#endif // Basic mapping structure struct IRToCommandMappingStruct { @@ -72,13 +88,10 @@ struct IRDataForCommandDispatcherStruct { #define COMMAND_EMPTY 0xFF // code no command #endif -#define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return -#define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break -#define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return - class IRCommandDispatcher { public: void init(); + void printIRInfo(Print *aSerial); bool checkAndRunNonBlockingCommands(); bool checkAndRunSuspendedBlockingCommands(); @@ -107,7 +120,8 @@ class IRCommandDispatcher { bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command /* * Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP). - * Is reset by next IR command received. Can be reset by main loop, if command has stopped. + * It is set if a blocking IR command received, which cannot be executed directly. Can be reset by main loop, if command has stopped. + * It is reset before executing a blocking command. */ volatile bool requestToStopReceived; /* diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp index a11174e68..701103a1f 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp +++ b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp @@ -11,14 +11,14 @@ * A blocking command is stored and sets a stop flag for an already running blocking function to terminate. * The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands(). * - * Copyright (C) 2019-2022 Armin Joachimsmeyer + * Copyright (C) 2019-2024 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * - * ServoEasing is free software: you can redistribute it and/or modify + * IRCommandDispatcher is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. @@ -31,6 +31,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +/* + * Program behavior is modified by the following macros + * USE_TINY_IR_RECEIVER + * USE_IRMP_LIBRARY + * IR_COMMAND_HAS_MORE_THAN_8_BIT + */ + #ifndef _IR_COMMAND_DISPATCHER_HPP #define _IR_COMMAND_DISPATCHER_HPP @@ -38,6 +46,10 @@ #include "IRCommandDispatcher.h" +#if !defined(STR_HELPER) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif /* * Enable this to see information on each call. * Since there should be no library which uses Serial, it should only be enabled for development purposes. @@ -73,6 +85,17 @@ void IRCommandDispatcher::init() { initPCIInterruptForTinyReceiver(); } +/* + * @return true, if IR Receiver is attached + */ +void IRCommandDispatcher::printIRInfo(Print *aSerial) { + aSerial->println(); + // For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h + aSerial->print(F("Listening to IR remote of type ")); + aSerial->print(IR_REMOTE_NAME); + aSerial->println(F(" at pin " STR(IR_RECEIVE_PIN))); +} + /* * This is the TinyReceiver callback function, which is called if a complete command was received * It checks for right address and then call the dispatcher @@ -153,11 +176,11 @@ void handleReceivedIRData() { #endif // elif defined(USE_IRMP_LIBRARY) /* - * The main dispatcher function - * Sets flags justCalledRegularIRCommand, executingBlockingCommand - * @param aCallBlockingCommandImmediately Run blocking command directly, otherwise set request to stop to true - * and store command for main loop to execute by checkAndRunSuspendedBlockingCommands(). - * Should be false if called by ISR. + * The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands() + * Non blocking commands are executed directly, blocking commands are executed if enabled by parameter and no other command is just running. + * Otherwise request to stop (requestToStopReceived) is set and command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands(). + * Sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived + * @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. Should be false if called by ISR in order not to block ISR. */ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) { if (IRReceivedData.command == COMMAND_EMPTY) { @@ -200,21 +223,31 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate } /* - * lets start a new turn + * Execute commands */ - requestToStopReceived = false; - bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING); if (tIsNonBlockingCommand) { // short command here, just call CD_INFO_PRINT(F("Run non blocking command: ")); CD_INFO_PRINTLN(tCommandName); +#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER) + /* + * Do (non blocking) buzzer feedback before command is executed + */ + if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { + tone(BUZZER_PIN, 2200, 50); + } +#endif IRMapping[i].CommandToCall(); } else { + /* + * Blocking command here + */ if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) { /* - * here we are called from main loop to execute a command + * Here no blocking command was running and we are called from main loop */ + requestToStopReceived = false; // Do not stop the command executed now justCalledBlockingCommand = true; currentBlockingCommandCalled = IRReceivedData.command; // set lock for recursive calls lastBlockingCommandCalled = IRReceivedData.command; // set history, can be evaluated by main loop @@ -224,6 +257,15 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate CD_INFO_PRINT(F("Run blocking command: ")); CD_INFO_PRINTLN(tCommandName); +#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER) + /* + * Do (non blocking) buzzer feedback before command is executed + */ + if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { + tone(BUZZER_PIN, 2200, 50); + } +#endif + IRMapping[i].CommandToCall(); #if defined(TRACE) Serial.println(F("End of blocking command")); @@ -231,7 +273,9 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate currentBlockingCommandCalled = COMMAND_EMPTY; } else { /* - * Do not run command directly, but set request to stop to true and store command for main loop to execute + * Called by ISR or another command still running. + * Do not run command directly, but set request to stop to true and store command + * for main loop to execute by checkAndRunSuspendedBlockingCommands() */ BlockingCommandToRunNext = IRReceivedData.command; requestToStopReceived = true; // to stop running command @@ -256,25 +300,29 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { */ if (BlockingCommandToRunNext != COMMAND_EMPTY) { - CD_INFO_PRINT(F("Take stored command = 0x")); + CD_INFO_PRINT(F("Run stored command=0x")); CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX); IRReceivedData.command = BlockingCommandToRunNext; BlockingCommandToRunNext = COMMAND_EMPTY; IRReceivedData.isRepeat = false; + requestToStopReceived = false; // Do not stop the command executed now checkAndCallCommand(true); return true; } return false; } +/* + * Not used internally + */ #if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunNext) #else void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext) #endif { - CD_INFO_PRINT(F("Set next command to 0x")); + CD_INFO_PRINT(F("Set next command to run to 0x")); CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX); BlockingCommandToRunNext = aBlockingCommandToRunNext; requestToStopReceived = true; @@ -296,7 +344,6 @@ bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) { } void IRCommandDispatcher::printIRCommandString(Print *aSerial) { - aSerial->print(F("IRCommand=")); for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { if (IRReceivedData.command == IRMapping[i].IRCode) { aSerial->println(reinterpret_cast(IRMapping[i].CommandString)); diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 81604dd43..cafbe9df4 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -60,7 +60,7 @@ */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. -//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. diff --git a/src/TinyIR.h b/src/TinyIR.h index bfcff36af..9a34ce9f3 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -247,6 +247,7 @@ struct TinyIRReceiverCallbackDataStruct { }; extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; +bool isIRReceiverAttachedForTinyReceiver(); bool initPCIInterruptForTinyReceiver(); bool enablePCIInterruptForTinyReceiver(); void disablePCIInterruptForTinyReceiver(); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 19f692707..d3302aa95 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -58,7 +58,7 @@ * - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED. * - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory. * - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory. - * - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. + * - USE_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 both 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. @@ -78,7 +78,7 @@ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. -//#define USE_ONKYO_PROTOCOL // Like NEC, but take both the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. +//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. @@ -423,6 +423,17 @@ bool isTinyReceiverIdle() { return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK); } +/* + * Checks if IR_RECEIVE_PIN is connected and high + * @return true, if IR Receiver is attached + */ +bool isIRReceiverAttachedForTinyReceiver() { + pinModeFast(IR_RECEIVE_PIN, OUTPUT); + digitalWriteFast(IR_RECEIVE_PIN, LOW); // discharge pin capacity + pinModeFast(IR_RECEIVE_PIN, INPUT); + return digitalRead(IR_RECEIVE_PIN); // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast. +} + /** * Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode. * Then call enablePCIInterruptForTinyReceiver() From 7c7ced8ecb3ed291af3d813ea65e214f2feb0747 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 14 Feb 2024 01:34:48 +0100 Subject: [PATCH 026/133] Closes #1199 --- Contributors.md | 1 + changelog.md | 2 +- src/ir_Pronto.hpp | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Contributors.md b/Contributors.md index 00dd4c826..7ca80549a 100644 --- a/Contributors.md +++ b/Contributors.md @@ -30,5 +30,6 @@ These are the active contributors of this project that you may contact if there - [Daniel Wallner](https://github.com/danielwallner) Bang & Olufsen protocol. - [slott](https://stackoverflow.com/users/11680056/sklott) Seeduino print(unsigned long long...) support. - [Joe Ostrander](https://github.com/joeostrander) Added support for attiny1614. +- [Buzzerb](https://github.com/Buzzerb) Added Extended NEC Protocol macro to TinyIR. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/changelog.md b/changelog.md index 0f1f2e934..8f3cec43d 100644 --- a/changelog.md +++ b/changelog.md @@ -4,7 +4,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.2.2 - Added convenience function isIRReceiverAttachedForTinyReceiver(). -- Added Extended NEC Protocol to TinyIR by Butzerb +- Added Extended NEC Protocol macro to TinyIR by Buzzerb. # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 2a8c9bc32..948ab8924 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -174,7 +174,7 @@ void IRsend::sendPronto(const char *str, int_fast8_t aNumberOfRepeats) { void IRsend::sendPronto_PF(uint_farptr_t str, int_fast8_t aNumberOfRepeats) { size_t len = strlen_PF(str); char work[len + 1]; - strncpy_PF(work, str, len); + strcpy_PF(work, str); // We know that string including terminating character fits in work sendPronto(work, aNumberOfRepeats); } @@ -182,7 +182,7 @@ void IRsend::sendPronto_PF(uint_farptr_t str, int_fast8_t aNumberOfRepeats) { void IRsend::sendPronto_P(const char *str, int_fast8_t aNumberOfRepeats) { size_t len = strlen_P(str); char work[len + 1]; - strncpy_P(work, str, len); + strcpy_P(work, str); sendPronto(work, aNumberOfRepeats); } #endif @@ -190,7 +190,7 @@ void IRsend::sendPronto_P(const char *str, int_fast8_t aNumberOfRepeats) { void IRsend::sendPronto(const __FlashStringHelper *str, int_fast8_t aNumberOfRepeats) { size_t len = strlen_P(reinterpret_cast(str)); char work[len + 1]; - strncpy_P(work, reinterpret_cast(str), len); + strcpy_P(work, reinterpret_cast(str)); return sendPronto(work, aNumberOfRepeats); } From 483aaa2cc3d29d32a1cd0736722aff69e65e14fe Mon Sep 17 00:00:00 2001 From: Buzzerb <33309634+Buzzerb@users.noreply.github.com> Date: Thu, 15 Feb 2024 23:00:20 +1100 Subject: [PATCH 027/133] Add ExtendedNEC support to TinyIRSender and move NEC2 to arguments (#1202) * Add ExtendedNEC support to TinyIRSender and move NEC2 from flag to argument Added ExtendedNEC support to TinyIRSender. Also redesigned TinyIRSender's handling of sending NEC2 repeats from a compile time flag to an argument in the send functions for NEC variants, as per discussion #1201. Modified the example script TinySender to support these changes/additions and fix a bug. Finally updated/made consistent some comments across various files and the README. Updated TinySender.ino to send using (almost*) all protocols simultaneously to demonstrate usage of TinyIRSender, as suggested in #1202 . Users can delete or comment out unneeded protocols. *(Not all combinations of NEC2 are demonstrated for brevity). --- README.md | 4 +- examples/TinySender/TinySender.ino | 54 +++++++++++++-------- src/TinyIR.h | 5 +- src/TinyIRReceiver.hpp | 2 +- src/TinyIRSender.hpp | 78 ++++++++++++++++++++++++------ 5 files changed, 104 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 3c7847a87..685d99717 100644 --- a/README.md +++ b/README.md @@ -447,7 +447,7 @@ void loop() { #include "TinyIRSender.hpp" void setup() { - sendNECMinimal(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats. + sendNEC(3, 0, 11, 2); // Send address 0 and command 11 on pin 3 with 2 repeats. } void loop() {} @@ -604,7 +604,7 @@ They use pin change interrupt for on the fly decoding, which is the reason for t TinyReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075). The **[TinySender](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/TinySender/TinySender.ino)** example uses the **TinyIRSender** library which can **only send NEC, ONKYO and FAST protocols**.
-It sends NEC protocol codes in standard format with 8 bit address and 8 bit command as in SimpleSender example. +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 diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 6d8ff8af6..2d0fc16fe 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -1,10 +1,12 @@ /* - * TinySender.cpp + * TinySender.ino * - * Example for sending FAST or NEC protocol using TinyIR. + * Example for sending using TinyIR. By default sends simultaneously using all supported protocols + * To use a single protocol, simply delete or comment out all unneeded protocols in the main loop + * Program size is significantly reduced when using a single protocol + * For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, + * which does the same, but uses the IRRemote library (and is therefore much more flexible). * - * NEC protocol codes are sent in standard format with 8bit address and 8 bit command as in SimpleSender example. - * Saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, which does the same, but uses the IRRemote library (and is therefore much more flexible). * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: @@ -46,12 +48,6 @@ #include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's -//#define USE_FAST_PROTOCOL // Use FAST protocol. No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command -//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. -//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. -//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. -//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. - #include "TinyIRSender.hpp" void setup() { @@ -82,29 +78,47 @@ void loop() { */ Serial.println(); Serial.print(F("Send now:")); -#if defined(USE_FAST_PROTOCOL) Serial.print(F(" address=0x")); Serial.print(sAddress, HEX); -#endif Serial.print(F(" command=0x")); Serial.print(sCommand, HEX); Serial.print(F(" repeats=")); Serial.print(sRepeats); Serial.println(); - -#if defined(USE_FAST_PROTOCOL) - Serial.println(F("Send FAST with 8 bit address")); + + // Send with FAST + // No address and only 16 bits of data, interpreted as 8 bit command and 8 bit inverted command for parity checking + Serial.println(F("Send FAST with 8 bit command")); Serial.flush(); sendFAST(IR_SEND_PIN, sCommand, sRepeats); -#elif defined(USE_ONKYO_PROTOCOL) + + // Send with NEC + // NEC uses 8 bit address and 8 bit command each with 8 bit inverted parity checks + // However, sendNEC will accept 16 bit address and commands too (but remove the parity checks) + Serial.println(F("Send NEC with 8 bit address and command")); + Serial.flush(); + sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); + + // Send with Extended NEC + // Like NEC, but the address is forced 16 bits with no parity check + Serial.println(F("Send ExtendedNEC with 16 bit address and 8 bit command")); + Serial.flush(); + sendExtendedNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); + + // Send with ONKYO + // Like NEC, but both the address and command are forced 16 bits with no parity check Serial.println(F("Send ONKYO with 16 bit address and command")); Serial.flush(); sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats); -#else - Serial.println(F("Send NEC with 8 bit address")); + + // Send with NEC2 + // Instead of sending the NEC special repeat code, sends the full original frame for repeats + // Sending NEC2 is done by setting the optional bool NEC2Repeats argument to true (defaults to false) + // sendExtendedNEC and sendONKYO also support the NEC2Repeats argument for full frame repeats (not demonstrated here) + Serial.println(F("Send NEC2 with 8 bit address and command and original frame repeats")); Serial.flush(); - sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); -#endif + sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true); + /* * Increment send values * Also increment address just for demonstration, which normally makes no sense diff --git a/src/TinyIR.h b/src/TinyIR.h index 9a34ce9f3..f479f56a0 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -256,10 +256,11 @@ void printTinyReceiverResultMinimal(Print *aSerial); void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); -void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); // Send NEC with 16 bit command, even if aCommand < 0x100 +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100 void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0) __attribute__ ((deprecated ("Renamed to sendNEC()."))); -void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); +void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); /* * Version 2.0.0 - 10/2023 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index d3302aa95..2b5a75e55 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -59,7 +59,7 @@ * - NO_LED_FEEDBACK_CODE Disables the feedback LED function. Saves 14 bytes program memory. * - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory. * - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. - * - USE_ONKYO_PROTOCOL Like NEC, but take both the 16 bit address and command each 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. diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 03d0b9334..a26593d67 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -105,12 +105,12 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { } /* - * Send NEC with 16 bit command, even if aCommand < 0x100 + * Send NEC with 16 bit address and command, even if aCommand < 0x100 (I.E. ONKYO) * @param aAddress - The 16 bit address to send. * @param aCommand - The 16 bit command to send. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. */ -void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -118,13 +118,10 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); -#if !defined(ENABLE_NEC2_REPEATS) - if (tNumberOfCommands < aNumberOfRepeats + 1) { + if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 - } else -#endif - { + } else { // send header delayMicroseconds(NEC_HEADER_SPACE); LongUnion tData; @@ -158,7 +155,7 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast } /* - * Send NEC with 8 or 16 bit address or data depending on the values of aAddress and aCommand. + * Send NEC with 8 or 16 bit address or command depending on the values of aAddress and aCommand. * @param aAddress - If aAddress < 0x100 send 8 bit address and 8 bit inverted address, else send 16 bit address. * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. @@ -166,7 +163,7 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { sendNEC(aSendPin, aAddress, aCommand, aNumberOfRepeats); // sendNECMinimal() is deprecated } -void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -174,13 +171,10 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); -#if !defined(ENABLE_NEC2_REPEATS) - if (tNumberOfCommands < aNumberOfRepeats + 1) { + if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 - } else -#endif - { + } else { // send header delayMicroseconds(NEC_HEADER_SPACE); LongUnion tData; @@ -228,6 +222,62 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ } } +/* + * Send Extended NEC with a forced 16 bit address and 8 or 16 bit command depending on the value of aCommand. + * @param aAddress - Send 16 bit address. + * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. + * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + */ +void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { + pinModeFast(aSendPin, OUTPUT); + + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; + while (tNumberOfCommands > 0) { + unsigned long tStartOfFrameMillis = millis(); + + sendMark(aSendPin, NEC_HEADER_MARK); + if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { + // send the NEC special repeat + delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 + } else { + // send header + delayMicroseconds(NEC_HEADER_SPACE); + LongUnion tData; + tData.UWord.LowWord = aAddress; + if (aCommand > 0xFF) { + tData.UWord.HighWord = aCommand; + } else { + tData.UByte.MidHighByte = aCommand; + tData.UByte.HighByte = ~aCommand; // LSB first + } + // Send data + for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { + sendMark(aSendPin, NEC_BIT_MARK); // constant mark length + + if (tData.ULong & 1) { + delayMicroseconds(NEC_ONE_SPACE); + } else { + delayMicroseconds(NEC_ZERO_SPACE); + } + tData.ULong >>= 1; // shift command for next bit + } + } // send stop bit + sendMark(aSendPin, NEC_BIT_MARK); + + tNumberOfCommands--; + // skip last delay! + if (tNumberOfCommands > 0) { + /* + * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. + */ + auto tFrameDurationMillis = millis() - tStartOfFrameMillis; + if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { + delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis); + } + } + } +} + /* * LSB first, send header, command, inverted command and stop bit */ From 2c2be06431dde604e7fa6fccc07733021a5aed8a Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 15 Feb 2024 13:12:12 +0100 Subject: [PATCH 028/133] Bumped TinyIR version to 2.1.0 --- Contributors.md | 2 +- examples/TinySender/TinySender.ino | 24 ++++++++++++------------ src/TinyIR.h | 13 ++++++++----- src/TinyIRReceiver.hpp | 2 +- src/TinyIRSender.hpp | 17 ++++++++++------- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/Contributors.md b/Contributors.md index 7ca80549a..349ccec14 100644 --- a/Contributors.md +++ b/Contributors.md @@ -30,6 +30,6 @@ These are the active contributors of this project that you may contact if there - [Daniel Wallner](https://github.com/danielwallner) Bang & Olufsen protocol. - [slott](https://stackoverflow.com/users/11680056/sklott) Seeduino print(unsigned long long...) support. - [Joe Ostrander](https://github.com/joeostrander) Added support for attiny1614. -- [Buzzerb](https://github.com/Buzzerb) Added Extended NEC Protocol macro to TinyIR. +- [Buzzerb](https://github.com/Buzzerb) Added Extended NEC protocol to TinyIR and making it more consistent. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 2d0fc16fe..4af49883b 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -1,10 +1,10 @@ /* - * TinySender.ino + * TinySender.cpp * * Example for sending using TinyIR. By default sends simultaneously using all supported protocols * To use a single protocol, simply delete or comment out all unneeded protocols in the main loop * Program size is significantly reduced when using a single protocol - * For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, + * For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, * which does the same, but uses the IRRemote library (and is therefore much more flexible). * * @@ -23,7 +23,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -85,32 +85,32 @@ void loop() { Serial.print(F(" repeats=")); Serial.print(sRepeats); Serial.println(); - - // Send with FAST + + // Send with FAST // No address and only 16 bits of data, interpreted as 8 bit command and 8 bit inverted command for parity checking Serial.println(F("Send FAST with 8 bit command")); Serial.flush(); sendFAST(IR_SEND_PIN, sCommand, sRepeats); - - // Send with NEC + + // Send with NEC // NEC uses 8 bit address and 8 bit command each with 8 bit inverted parity checks // However, sendNEC will accept 16 bit address and commands too (but remove the parity checks) Serial.println(F("Send NEC with 8 bit address and command")); Serial.flush(); sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); - + // Send with Extended NEC - // Like NEC, but the address is forced 16 bits with no parity check + // Like NEC, but the address is forced 16 bits with no parity check Serial.println(F("Send ExtendedNEC with 16 bit address and 8 bit command")); Serial.flush(); sendExtendedNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); - + // Send with ONKYO // Like NEC, but both the address and command are forced 16 bits with no parity check Serial.println(F("Send ONKYO with 16 bit address and command")); Serial.flush(); sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats); - + // Send with NEC2 // Instead of sending the NEC special repeat code, sends the full original frame for repeats // Sending NEC2 is done by setting the optional bool NEC2Repeats argument to true (defaults to false) @@ -118,7 +118,7 @@ void loop() { Serial.println(F("Send NEC2 with 8 bit address and command and original frame repeats")); Serial.flush(); sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true); - + /* * Increment send values * Also increment address just for demonstration, which normally makes no sense diff --git a/src/TinyIR.h b/src/TinyIR.h index f479f56a0..4f89fa2c5 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -34,9 +34,9 @@ * @{ */ -#define VERSION_TINYIR "2.0.0" +#define VERSION_TINYIR "2.1.0" #define VERSION_TINYIR_MAJOR 2 -#define VERSION_TINYIR_MINOR 0 +#define VERSION_TINYIR_MINOR 1 #define VERSION_TINYIR_PATCH 0 // The change log is at the bottom of the file @@ -256,13 +256,16 @@ void printTinyReceiverResultMinimal(Print *aSerial); void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); -void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100 +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100 void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0) __attribute__ ((deprecated ("Renamed to sendNEC()."))); -void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); -void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool NEC2Repeats = false); +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); +void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); /* + * Version 2.1.0 - 2/2024 + * - New sendExtendedNEC() function and new parameter aSendNEC2Repeats. + * * Version 2.0.0 - 10/2023 * - New TinyIRReceiverData which is filled with address, command and flags. * - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 2b5a75e55..9f7874358 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -28,7 +28,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index a26593d67..65a1fe18b 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -19,7 +19,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -109,8 +109,9 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { * @param aAddress - The 16 bit address to send. * @param aCommand - The 16 bit command to send. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ -void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { +void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -118,7 +119,7 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); - if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { + if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 } else { @@ -159,11 +160,12 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast * @param aAddress - If aAddress < 0x100 send 8 bit address and 8 bit inverted address, else send 16 bit address. * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { sendNEC(aSendPin, aAddress, aCommand, aNumberOfRepeats); // sendNECMinimal() is deprecated } -void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { +void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -171,7 +173,7 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); - if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { + if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 } else { @@ -227,8 +229,9 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ * @param aAddress - Send 16 bit address. * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. + * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ -void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool NEC2Repeats) { +void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -236,7 +239,7 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); - if ((!NEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { + if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds(NEC_REPEAT_HEADER_SPACE); // - 2250 } else { From ef69840a5f0ee74e27c4bb7ee013ada303477870 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 15 Feb 2024 18:50:02 +0100 Subject: [PATCH 029/133] Improved printIRSendUsage() --- README.md | 2 ++ src/IRReceive.hpp | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 685d99717..6315c9ee5 100644 --- a/README.md +++ b/README.md @@ -387,6 +387,8 @@ 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. + 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. diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index fee76b27f..3f92f890b 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1243,6 +1243,7 @@ uint32_t IRrecv::getTotalDurationOfRawData() { /** * Function to print values and flags of IrReceiver.decodedIRData in one line. * Ends with println(). + * !!!Attention: The result differs on a 8 bit or 32 bit platform!!! * * @param aSerial The Print object on which to write, for Arduino you can use &Serial. */ @@ -1250,15 +1251,16 @@ void IRrecv::printIRSendUsage(Print *aSerial) { if (decodedIRData.protocol != UNKNOWN && (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) { #if defined(DECODE_DISTANCE_WIDTH) - aSerial->print(F("Send with:")); uint_fast8_t tNumberOfArrayData = 0; if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) { # if __INT_WIDTH__ < 32 + aSerial->print(F("Send on a 8 bit platform with:")); tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1; if(tNumberOfArrayData > 1) { aSerial->println(); aSerial->print(F(" uint32_t tRawData[]={0x")); # else + aSerial->print(F("Send on a 32 bit platform with:")); tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1; if(tNumberOfArrayData > 1) { aSerial->println(); @@ -1358,6 +1360,11 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(F(");")); aSerial->println(); } +#if defined(DECODE_DISTANCE_WIDTH) + else { + aSerial->print(F("Send with:")); + } +#endif } /** From 3930c4148afe7295a6d24342d067a159dc6833b0 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 23 Feb 2024 19:28:33 +0100 Subject: [PATCH 030/133] Fixed sendSamsung() / sendSamsungLG() bug Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd() Added rawlen and initialGap to IRData Bumped version to 4.3.0 --- .github/workflows/LibraryBuild.yml | 42 ++--- README.md | 131 +++++++------- changelog.md | 5 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 8 +- examples/ReceiveDemo/ReceiveDemo.ino | 166 +++++++++--------- examples/ReceiveDump/ReceiveDump.ino | 7 +- .../ReceiveOneAndSendMultiple.ino | 4 +- examples/SimpleReceiver/SimpleReceiver.ino | 17 +- .../SimpleReceiverWithCallback.ino | 22 +-- examples/UnitTest/UnitTest.ino | 92 ++++++---- examples/UnitTest/UnitTest.log | 133 +++++++++----- library.json | 2 +- library.properties | 4 +- src/IRProtocol.h | 13 +- src/IRProtocol.hpp | 8 +- src/IRReceive.hpp | 131 +++++++++----- src/IRSend.hpp | 18 +- src/IRVersion.h | 6 +- src/IRremoteInt.h | 7 +- src/ir_BangOlufsen.hpp | 20 +-- src/ir_BoseWave.hpp | 4 +- src/ir_Denon.hpp | 8 +- src/ir_DistanceWidthProtocol.hpp | 10 +- src/ir_FAST.hpp | 6 +- src/ir_JVC.hpp | 12 +- src/ir_Kaseikyo.hpp | 4 +- src/ir_LG.hpp | 20 +-- src/ir_Lego.hpp | 12 +- src/ir_MagiQuest.hpp | 4 +- src/ir_NEC.hpp | 10 +- src/ir_Others.hpp | 2 +- src/ir_Pronto.hpp | 8 +- src/ir_RC5_RC6.hpp | 12 +- src/ir_Samsung.hpp | 67 ++++--- src/ir_Sony.hpp | 10 +- 35 files changed, 579 insertions(+), 446 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 908dec28a..734432f14 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -60,9 +60,9 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect - - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro # - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 @@ -193,26 +193,26 @@ jobs: # # 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:attinyx5micr:LTO=enable,sketchclock=16pll +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER - - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - platform-url: http://drazzy.com/package_drazzy.com_index.json - required-libraries: ATtinySerialOut - sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# platform-url: http://drazzy.com/package_drazzy.com_index.json +# required-libraries: ATtinySerialOut +# sketch-names: TinyReceiver.ino,IRremoteInfo.ino,SimpleReceiver.ino,ReceiveDemo.ino,ControlRelay.ino,SimpleSender.ino,SendDemo.ino,SendRawDemo.ino,SendAndReceive.ino +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER # # MegaCore diff --git a/README.md b/README.md index 6315c9ee5..c011d481d 100644 --- a/README.md +++ b/README.md @@ -30,56 +30,56 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr -# Overview -- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-ir-protocols) -- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote#features) - * [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-4x) - * [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote#new-features-with-version-3x) -- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote#converting-your-2x-program-to-the-4x-version) - * [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes) -- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote#errors-with-using-the-3x-versions-for-old-tutorials) - * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote#staying-on-2x) -- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote#why-hpp-instead-of-cpp) -- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote#using-the-new-hpp-files) -- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#receiving-ir-codes) - * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote#decodedirdata-structure) - * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#ambiguous-protocols) - * [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#unknown-protocol) -- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote#sending-ir-codes) - * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote#send-pin) - + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote#list-of-public-ir-code-databases) -- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote#tiny-nec-receiver-and-sender) -- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#the-fast-protocol) -- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote#faq-and-hints) - * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc) - * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote#does-not-workcompile-with-another-library) - * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote#multiple-ir-receiver) - * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote#increase-strength-of-sent-output-signal) - * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-cpu-clock-frequency) - * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote#bang--olufsen-protocol) -- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote#handling-unknown-protocols) - * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote#disclaimer) - * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolpulse_distance) - * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote#protocolunknown) - * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-deal-with-protocols-not-supported-by-irremote) -- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#examples-for-this-library) -- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote#wokwi-online-examples) -- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote#issues-and-discussions) -- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library) - + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#changing-include-h-files-with-arduino-ide) - + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote#modifying-compile-options--macros-with-sloeber-ide) -- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote#supported-boards) -- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage) - * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite) - * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#hardware-pwm-signal-generation-for-sending) - * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote#why-do-we-use-30-duty-cycle-for-sending) -- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote#how-we-decode-signals) -- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote#nec-encoding-diagrams) -- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries) -- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote#useful-links) +# Table of content +- [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) +- [Features](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#features) + * [New features with version 4.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-4x) + * [New features with version 3.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-with-version-3x) +- [Converting your 2.x program to the 4.x version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#converting-your-2x-program-to-the-4x-version) + * [How to convert old MSB first 32 bit IR data codes to new LSB first 32 bit IR data codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes) +- [Errors with using the 3.x versions for old tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#errors-with-using-the-3x-versions-for-old-tutorials) + * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#staying-on-2x) +- [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp) +- [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files) +- [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes) + * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure) + * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols) + * [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#unknown-protocol) +- [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) + * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin) + + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) +- [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) +- [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) +- [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) + * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc) + * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library) + * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver) + * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#increase-strength-of-sent-output-signal) + * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency) + * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol) +- [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols) + * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer) + * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance) + * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown) + * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote) +- [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library) +- [WOKWI online examples](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#wokwi-online-examples) +- [Issues and discussions](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#issues-and-discussions) +- [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library) + + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#changing-include-h-files-with-arduino-ide) + + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) +- [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-boards) +- [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) + * [Incompatibilities to other libraries and Arduino commands like tone() and analogWrite()](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#incompatibilities-to-other-libraries-and-arduino-commands-like-tone-and-analogwrite) + * [Hardware-PWM signal generation for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#hardware-pwm-signal-generation-for-sending) + * [Why do we use 30% duty cycle for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-do-we-use-30-duty-cycle-for-sending) +- [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-we-decode-signals) +- [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#nec-encoding-diagrams) +- [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries) +- [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#useful-links) - [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md) -- [License](https://github.com/Arduino-IRremote/Arduino-IRremote#license) -- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote#copyright) +- [License](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#license) +- [Copyright](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#copyright)
@@ -110,9 +110,10 @@ Protocols can be switched off and on by defining macros before the line `#includ - New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols. - Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`. - RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before. -- Callback after receiving a command - It calls your code as soon as a message was received. +- **Callback** after receiving a command - It calls your code as soon as a message was received. - Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. - New FAST protocol. +- Automatic printout of the **corresponding send function** with printIRSendUsage(). #### Converting your 3.x program to the 4.x version - You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder). @@ -131,9 +132,9 @@ Protocols can be switched off and on by defining macros before the line `#includ - Allows for the generation of non PWM signal to just **simulate an active low receiver signal** for direct connect to existent receiving devices without using IR. - Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
Reduces memory footprint and decreases decoding time. -- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote#minimal-nec-receiver), which **does not require any timer resource**. +- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**. -[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote#quick-comparison-of-5-arduino-ir-receiving-libraries). +[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries).
@@ -155,7 +156,7 @@ If IR_SEND_PIN is not defined (before the line `#include `) you mu - Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`. - The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data for **NEC** and **JVC** were renamed to `sendNECMSB`, and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized.
-For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes). +For converting MSB codes to LSB see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-convert-old-msb-first-32-bit-ir-data-codes-to-new-lsb-first-32-bit-ir-data-codes). ### Example #### Old 2.x program: @@ -198,7 +199,6 @@ void setup() void loop() { if (IrReceiver.decode()) { Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data - // USE NEW 3.x FUNCTIONS IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data ... @@ -232,7 +232,7 @@ You may use `bitreverseOneByte()` or `bitreverse32Bit()` for this. # Errors with using the 4.x versions for old tutorials If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
-Most likely your code will run and you will not miss the new features... +Most likely your code will run and you will not miss the new features.
@@ -367,11 +367,14 @@ Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ON ### NEC, NEC2 On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame. This enables an easy distinction between long presses and repeated presses and saves a bit of battery energy. -This behavior is quite unique for NEC and its derived protocols like LG. +This behavior is quite unique for NEC and its derived protocols like LG and Samsung. -So there are of course also remote control systems, which uses the NEC protocol but on a long press just repeat the first frame instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
+But of course there are also remote control systems, that uses the NEC protocol but only repeat the first frame when a long press is made instead of sending the special short repeat frame. We named this the **NEC2** protocol and it is sent with `sendNEC2()`.
But be careful, the NEC2 protocol can only be detected by the NEC library decoder **after** the first frame and if you do a long press! +### Samsung, SamsungLG +On a long press, the **SamsungLG protocol** does not repeat its frame, it sends a special short repeat frame. + ## Unknown protocol If your protocol seems not to be supported by this library, you may try the [IRMP library](https://github.com/IRMP-org/IRMP). @@ -401,7 +404,7 @@ The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957 ## Send pin Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active. -If `IR_SEND_PIN` is specified (as 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#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. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library). ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html @@ -423,7 +426,7 @@ http://www.harctoolbox.org/IR-resources.html For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included,
which has very **small code size of 500 bytes and does NOT require any timer**. -Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote#irdispatcherdemo) examples.
+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`. ### TinyIRReceiver usage @@ -510,7 +513,7 @@ There are some other solutions to this on more powerful processors, ## Does not work/compile with another library **Another library is only working/compiling** if you deactivate the line `IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);`.
-This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). +This is often due to **timer resource conflicts** with the other library. Please see [below](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). ## Multiple IR receivers IRreceiver consists of one timer triggered function reading the digital IR signal value from one pin every 50 µs.
@@ -701,7 +704,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | | `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | -| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | +| `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). | | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | | `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | @@ -728,7 +731,7 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the fixed function `void handleReceivedTinyIRData()` each time a frame or repeat is received. | The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. -| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote#tinyreceiver--tinysender) for receiving IR codes. | +| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. | | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | | `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | @@ -862,7 +865,7 @@ For other boards/platforms you must look for the appropriate section guarded by ### Stop and start timer Another approach can be to share the timer **sequentially** if their functionality is used only for a short period of time like for the **Arduino tone() command**. An example can be seen [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), where the timer settings for IR receive are restored after the tone has stopped. -For this we must call `IrReceiver.start()` or better `IrReceiver.start(microsecondsOfToneDuration)`.
+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. ## Hardware-PWM signal generation for sending @@ -886,7 +889,7 @@ And believe me, if you send a 525 µs signal, your receiver will output som Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
And since the receivers generated marks are longer or shorter than the spaces, -we have introduced the [`MARK_EXCESS_MICROS`](https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library) macro +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**. diff --git a/changelog.md b/changelog.md index 8f3cec43d..19d5d704f 100644 --- a/changelog.md +++ b/changelog.md @@ -2,9 +2,12 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master -# 4.2.2 +# 4.3.0 - Added convenience function isIRReceiverAttachedForTinyReceiver(). - Added Extended NEC Protocol macro to TinyIR by Buzzerb. +- Fixed sendSamsung() / sendSamsungLG() bug. +- Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). +- Added rawlen and initialGap to IRData. # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 6daddec6c..1b420c53f 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -231,7 +231,7 @@ void loop() { } else { // play tone auto tStartMillis = millis(); - IrReceiver.stop(); + IrReceiver.stopTimer(); tone(TONE_PIN, 2200); if ((IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) @@ -251,7 +251,7 @@ void loop() { noTone(TONE_PIN); // Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement. - IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK)); + IrReceiver.restartTimerWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK)); #if defined(USE_LCD) printIRResultOnLCD(); @@ -277,11 +277,11 @@ void loop() { #if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) printsVCCVoltageMillivoltOnLCD(); #endif - IrReceiver.stop(); + IrReceiver.stopTimer(); tone(TONE_PIN, 2200); delay(50); noTone(TONE_PIN); - IrReceiver.startWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK)); + IrReceiver.restartTimerWithTicksToAdd(50 * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK)); } #if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE) diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index be18a649c..222e9ce47 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -3,14 +3,14 @@ * * Demonstrates receiving IR codes with the IRremote library and the use of the Arduino tone() function with this library. * Long press of one IR button (receiving of multiple repeats for one command) is detected. - * If debug button is pressed (pin connected to ground) a long output is generated. + * If debug button is pressed (pin connected to ground) a long output is generated, which may disturb detecting of repeats. * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * ************************************************************************************ * MIT License * - * Copyright (c) 2020-2023 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -54,18 +54,14 @@ //#define DECODE_SONY //#define DECODE_RC5 //#define DECODE_RC6 - //#define DECODE_BOSEWAVE //#define DECODE_LEGO_PF //#define DECODE_MAGIQUEST //#define DECODE_WHYNTER //#define DECODE_FAST - //#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols //#define DECODE_HASH // special decoder for all protocols - //#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY! - #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. // !!! Enabling B&O disables detection of Sony, because the repeat gap for SONY is smaller than the B&O frame gap :-( !!! //#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY! @@ -108,6 +104,8 @@ #define DEBUG_BUTTON_PIN 6 #endif +void generateTone(); +void handleOverflow(); bool detectLongPress(uint16_t aLongPressDurationMillis); void setup() { @@ -153,7 +151,6 @@ void setup() { Serial.print(MARK_EXCESS_MICROS); Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding")); #endif - } void loop() { @@ -164,99 +161,60 @@ void loop() { * E.g. command is in IrReceiver.decodedIRData.command * address is in command is in IrReceiver.decodedIRData.address * and up to 32 bit raw data in IrReceiver.decodedIRData.decodedRawData - * - * At 115200 baud, printing takes 40 ms for NEC protocol and 10 ms for NEC repeat */ if (IrReceiver.decode()) { Serial.println(); -#if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604 +#if FLASHEND < 0x3FFF // + // For less than 16k flash, only print a minimal summary of received data + IrReceiver.printIRResultMinimal(&Serial); +#else + + /* + * + */ if (IrReceiver.decodedIRData.flags & IRDATA_FLAGS_WAS_OVERFLOW) { - Serial.println(F("Overflow detected")); - Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__)); - // see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library -# if !defined(ESP8266) && !defined(NRF5) + handleOverflow(); + } else { /* - * do double beep - */ -# if !defined(ESP32) - IrReceiver.stop(); // ESP32 uses another timer for tone() -# endif - tone(TONE_PIN, 1100, 10); - delay(50); - tone(TONE_PIN, 1100, 10); - delay(50); -# if !defined(ESP32) - IrReceiver.start(100000); // to compensate for 100 ms stop of receiver. This enables a correct gap measurement. -# endif -# endif + * 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) { + /* + * For SONY the tone prevents the detection of a repeat after the 15 ms SONY gap. + * In debug mode and for unknown protocols, we need the time for extended output. + * Skipping tone will get exact gap time between transmissions and not running into repeat frames while wait for tone to end. + * This in turn enables the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value. + */ + generateTone(); + } - } else { - auto tStartMillis = millis(); -# if !defined(ESP32) - IrReceiver.stop(); // ESP32 uses another timer for tone() -# endif - tone(TONE_PIN, 2200); - - // No overflow, print a short summary of received data -# if defined(LOCAL_DEBUG) - IrReceiver.printIRResultShort(&Serial, true); -# else - IrReceiver.printIRResultShort(&Serial, true, digitalRead(DEBUG_BUTTON_PIN) == LOW); -# endif - // Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame - // so here we are 10 millis after end of frame. Sony20 has only a 12 ms repeat gap. - while ((millis() - tStartMillis) < 5) - ; - noTone(TONE_PIN); - -# if !defined(ESP32) - // Restore IR timer. millis() - tStartMillis to compensate for stop of receiver. This enables a correct gap measurement. - IrReceiver.startWithTicksToAdd((millis() - tStartMillis) * (MICROS_IN_ONE_MILLI / MICROS_PER_TICK)); -# endif - - IrReceiver.printIRSendUsage(&Serial); -# if defined(LOCAL_DEBUG) - IrReceiver.printIRResultRawFormatted(&Serial, true); -# else + /* + * Print info + */ if (IrReceiver.decodedIRData.protocol == UNKNOWN || digitalRead(DEBUG_BUTTON_PIN) == LOW) { - // We have an unknown protocol, print more info + // We have debug enabled or an unknown protocol, print extended info if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("Received noise or an unknown (or not yet enabled) protocol")); } IrReceiver.printIRResultRawFormatted(&Serial, true); + } else { + /* + * This is the info output for a successful receive in normal mode + */ + IrReceiver.printIRResultShort(&Serial); + IrReceiver.printIRSendUsage(&Serial); } -# endif } - - // tone on esp8266 works once, then it disables the successful IrReceiver.start() / timerConfigForReceive(). -# if !defined(ESP8266) && !defined(NRF5) && !defined(LOCAL_DEBUG) - if ((IrReceiver.decodedIRData.protocol != SONY) && (IrReceiver.decodedIRData.protocol != PULSE_WIDTH) - && (IrReceiver.decodedIRData.protocol != PULSE_DISTANCE) && (IrReceiver.decodedIRData.protocol != UNKNOWN) - && digitalRead(DEBUG_BUTTON_PIN) != LOW) { - /* - * If no debug mode or a valid protocol was received, play tone, wait and restore IR timer. - * For SONY the tone prevents the detection of a repeat - * Otherwise do not play a tone to get exact gap time between transmissions and not running into repeat frames while wait for tone to end. - * This will give the next CheckForRecordGapsMicros() call a chance to eventually propose a change of the current RECORD_GAP_MICROS value. - */ -# if !defined(ESP32) - IrReceiver.stop(); // ESP32 uses another timer for tone() -# endif - tone(TONE_PIN, 2200, 8); -# if !defined(ESP32) - delay(8); - IrReceiver.start(8000); // Restore IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement. -# endif - } -# endif -#else // #if FLASHEND >= 0x3FFF - // Print a minimal summary of received data - IrReceiver.printIRResultMinimal(&Serial); #endif // #if FLASHEND >= 0x3FFF /* - * !!!Important!!! Enable receiving of the next value, - * since receiving has stopped after the end of the current received data packet. + * !!!Important!!! Enable receiving of the next value, because receiving + * has stopped after the end of the current received data packet. + * Do it here, to preserve raw data for printing with printIRResultRawFormatted() */ IrReceiver.resume(); @@ -289,6 +247,46 @@ void loop() { } +/* + * Stop receiver, generate a single beep and start receiver again + */ +void generateTone() { +#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). +# if defined(ESP32) // ESP32 uses another timer for tone() + tone(TONE_PIN, 2200, 5); +# else + IrReceiver.stopTimer(); // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too. + tone(TONE_PIN, 2200, 8); + delay(8); + IrReceiver.restartTimer(8000); // Restart IR timer. 8000 to compensate for 8 ms stop of receiver. This enables a correct gap measurement. +# endif +#endif +} + +void handleOverflow() { + Serial.println(F("Overflow detected")); + Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__)); + // see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library + +#if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). + /* + * Stop timer, generate a double beep and start timer again + */ +# if defined(ESP32) // ESP32 uses another timer for tone() + tone(TONE_PIN, 1100, 10); + delay(50); + tone(TONE_PIN, 1100, 10); +# else + IrReceiver.stopTimer(); + tone(TONE_PIN, 1100, 10); + delay(50); + tone(TONE_PIN, 1100, 10); + delay(50); + IrReceiver.restartTimer(100000); // to compensate for 100 ms stop of receiver. This enables a correct gap measurement. +# endif +#endif +} + unsigned long sMillisOfFirstReceive; bool sLongPressJustDetected; /** diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 4accf67ea..eb30f5b07 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -10,7 +10,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2022 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -88,6 +88,9 @@ void setup() { Serial.println(); Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!")); Serial.println(); + Serial.println(F("If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2, SamsungLG or LG2, which is determined by the repeats")); + Serial.println(); + } //+============================================================================= @@ -147,6 +150,6 @@ void loop() { // Serial.println(); // blank line between entries // } } - IrReceiver.resume(); // Prepare for the next value + IrReceiver.resume(); // Prepare for the next IR frame } } diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index 34baa144e..c59fa770e 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -190,7 +190,7 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { } # if !defined(ESP32) - IrReceiver.stop(); // ESP32 uses another timer for tone() + IrReceiver.stopTimer(); // ESP32 uses another timer for tone() # endif if (millis() < tWaitTimeAfterBoot) { // division by 1000 and printing requires much (8%) program memory @@ -218,7 +218,7 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { delay(200); # if !defined(ESP32) - IrReceiver.start(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement. + IrReceiver.restartTimer(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement. # endif Serial.println(F("Wait for \"not supported\" to disappear")); diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 12b950b2c..87ec5c1b8 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -94,23 +94,20 @@ void loop() { if (IrReceiver.decode()) { /* - * Print a short summary of received data + * Print a summary of received data */ - IrReceiver.printIRResultShort(&Serial); - IrReceiver.printIRSendUsage(&Serial); if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("Received noise or an unknown (or not yet enabled) protocol")); - // We have an unknown protocol here, print more info + // We have an unknown protocol here, print extended info IrReceiver.printIRResultRawFormatted(&Serial, true); + IrReceiver.resume(); // Do it here, to preserve raw data for printing with printIRResultRawFormatted() + } else { + IrReceiver.resume(); // Early enable receiving of the next IR frame + IrReceiver.printIRResultShort(&Serial); + IrReceiver.printIRSendUsage(&Serial); } Serial.println(); - /* - * !!!Important!!! Enable receiving of the next value, - * since receiving has stopped after the end of the current received data packet. - */ - IrReceiver.resume(); // Enable receiving of the next value - /* * Finally, check the received data and perform actions according to the received command */ diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index 3c1a3f40a..7a570a43e 100644 --- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino +++ b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino @@ -85,7 +85,7 @@ void setup() { IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler); Serial.print(F("Ready to receive IR signals of protocols: ")); - printActiveIRProtocols (&Serial); + printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); } @@ -94,9 +94,7 @@ void loop() { * Print in loop (interrupts are enabled here) if received data is available. */ if (sIRDataJustReceived) { - // Print a short summary of received data - IrReceiver.printIRResultShort(&Serial); - IrReceiver.printIRSendUsage(&Serial); + // Print a summary of received data if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("Received noise or an unknown (or not yet enabled) protocol")); /* @@ -105,6 +103,9 @@ void loop() { * and the the first mark of the next (repeat) data was yet received */ IrReceiver.printIRResultRawFormatted(&Serial, true); // + } else { + IrReceiver.printIRResultShort(&Serial); + IrReceiver.printIRSendUsage(&Serial); } Serial.println(); } @@ -124,6 +125,10 @@ IRAM_ATTR # endif void ReceiveCompleteCallbackHandler() { IrReceiver.decode(); // fill IrReceiver.decodedIRData + /* + * Enable receiving of the next value. + */ + IrReceiver.resume(); /* * Check the received data and perform actions according to the received command @@ -146,13 +151,4 @@ void ReceiveCompleteCallbackHandler() { */ sIRDataJustReceived = true; - /* - * Enable receiving of the next value. - * !!!Attention!!! - * After receiving the first mark of the next (repeat) data, 3 variables required for printing are reset/overwritten. - * - IrReceiver.irparams.rawlen - * - IrReceiver.irparams.rawbuf[0] - * - IrReceiver.irparams.OverflowFlag) - */ - IrReceiver.resume(); } diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 0402448b4..ce00030ef 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -288,7 +288,7 @@ void ReceiveCompleteCallbackHandler() { void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { // wait until signal has received while (!sDataJustReceived) { - }; + } sDataJustReceived = false; if (IrReceiver.decode()) { @@ -311,6 +311,8 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { IrReceiver.printIRResultRawFormatted(&Serial, true); } #endif + IrReceiver.resume(); // Early resume + if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("ERROR: Unknown protocol")); } else { @@ -334,9 +336,9 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { } } - IrReceiver.resume(); } else { Serial.println(F("No data received")); + IrReceiver.resume(); } Serial.println(); } @@ -350,7 +352,7 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { uint16_t sAddress = 0xFFF1; uint8_t sCommand = 0x76; uint16_t s16BitCommand = 0x9876; -#define sRepeats 0 // no unit test for repeats +uint8_t sRepeats = 0; void loop() { /* @@ -366,19 +368,29 @@ void loop() { Serial.println(F("Send NEC with 8 bit address")); Serial.flush(); - IrSender.sendNEC(sAddress & 0xFF, sCommand, sRepeats); + IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); + // + for (int8_t i = 0; i < sRepeats; i++) { + Serial.println(F("Repeat NEC frame for NEC2")); + Serial.flush(); + // if debug is enabled, printing time (50 ms) is too high anyway + delayMicroseconds(NEC_REPEAT_DISTANCE - 200); // 200 is just a guess + IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); + checkReceive(sAddress & 0xFF, sCommand); + } + delay(DELAY_AFTER_SEND); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal Serial.println(F("Send NEC with 16 bit address")); Serial.flush(); - IrSender.sendNEC(sAddress, sCommand, sRepeats); + IrSender.sendNEC(sAddress, sCommand, 0); checkReceive(sAddress, sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send NEC2 with 16 bit address")); Serial.flush(); - IrSender.sendNEC2(sAddress, sCommand, sRepeats); + IrSender.sendNEC2(sAddress, sCommand, 0); checkReceive(sAddress, sCommand); delay(DELAY_AFTER_SEND); @@ -418,7 +430,7 @@ void loop() { */ Serial.println(F("Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102)")); Serial.flush(); - IrSender.sendNECRaw(0x03040102, sRepeats); + IrSender.sendNECRaw(0x03040102, 0); checkReceive(0x0102, 0x304); delay(DELAY_AFTER_SEND); @@ -453,7 +465,7 @@ void loop() { * Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first */ Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance")); - Serial.println(F(" LSB first")); + Serial.println(F("-LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, PROTOCOL_IS_LSB_FIRST, 0, @@ -467,7 +479,7 @@ void loop() { delay(DELAY_AFTER_SEND); // The same with MSB first. Use bit reversed raw data of LSB first part - Serial.println(F(" MSB first")); + Serial.println(F("-MSB first")); # if __INT_WIDTH__ < 32 tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first tRawData[1] = 0x805; @@ -585,32 +597,32 @@ void loop() { Serial.println(F("Send Onkyo (NEC with 16 bit command)")); Serial.flush(); - IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, sRepeats); + IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, 0); checkReceive(sAddress, (sCommand + 1) << 8 | sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Apple")); Serial.flush(); - IrSender.sendApple(sAddress & 0xFF, sCommand, sRepeats); + IrSender.sendApple(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic")); Serial.flush(); - IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats); + IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, 0); checkReceive(sAddress & 0xFFF, sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID")); Serial.flush(); - IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711); + IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, 0, 0x4711); checkReceive(sAddress & 0xFFF, sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Kaseikyo_Denon variant")); Serial.flush(); - IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, sRepeats); + IrSender.sendKaseikyo_Denon(sAddress & 0xFFF, sCommand, 0); checkReceive(sAddress & 0xFFF, sCommand); delay(DELAY_AFTER_SEND); #endif @@ -618,13 +630,13 @@ void loop() { #if defined(DECODE_DENON) Serial.println(F("Send Denon")); Serial.flush(); - IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats); + IrSender.sendDenon(sAddress & 0x1F, sCommand, 0); checkReceive(sAddress & 0x1F, sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Denon/Sharp variant")); Serial.flush(); - IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats); + IrSender.sendSharp(sAddress & 0x1F, sCommand, 0); checkReceive(sAddress & 0x1F, sCommand); delay(DELAY_AFTER_SEND); #endif @@ -632,19 +644,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, sRepeats); + IrSender.sendSony(sAddress & 0x1F, sCommand, 0); checkReceive(sAddress & 0x1F, sCommand & 0x7F); delay(DELAY_AFTER_SEND); Serial.println(F("Send Sony/SIRCS with 7 command and 8 address bits")); Serial.flush(); - IrSender.sendSony(sAddress & 0xFF, sCommand, sRepeats, SIRCS_15_PROTOCOL); + IrSender.sendSony(sAddress & 0xFF, sCommand, 0, SIRCS_15_PROTOCOL); checkReceive(sAddress & 0xFF, sCommand & 0x7F); delay(DELAY_AFTER_SEND); Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits")); Serial.flush(); - IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL); + IrSender.sendSony(sAddress & 0x1FFF, sCommand, 0, SIRCS_20_PROTOCOL); checkReceive(sAddress & 0x1FFF, sCommand & 0x7F); delay(DELAY_AFTER_SEND); #endif @@ -652,19 +664,19 @@ void loop() { #if defined(DECODE_SAMSUNG) Serial.println(F("Send Samsung 8 bit command")); Serial.flush(); - IrSender.sendSamsung(sAddress, sCommand, sRepeats); + IrSender.sendSamsung(sAddress, sCommand, 0); checkReceive(sAddress, sCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Samsung 16 bit command")); Serial.flush(); - IrSender.sendSamsung(sAddress, s16BitCommand, sRepeats); + IrSender.sendSamsung(sAddress, s16BitCommand, 0); checkReceive(sAddress, s16BitCommand); delay(DELAY_AFTER_SEND); Serial.println(F("Send Samsung48 16 bit command")); Serial.flush(); - IrSender.sendSamsung48(sAddress, s16BitCommand, sRepeats); + IrSender.sendSamsung48(sAddress, s16BitCommand, 0); checkReceive(sAddress, s16BitCommand); delay(DELAY_AFTER_SEND); #endif @@ -672,13 +684,13 @@ void loop() { #if defined(DECODE_RC5) Serial.println(F("Send RC5")); Serial.flush(); - IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, sRepeats, true); // 5 address, 6 command bits + IrSender.sendRC5(sAddress & 0x1F, sCommand & 0x3F, 0, true); // 5 address, 6 command bits checkReceive(sAddress & 0x1F, sCommand & 0x3F); delay(DELAY_AFTER_SEND); Serial.println(F("Send RC5X with 7.th MSB of command set")); Serial.flush(); - IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, true); // 5 address, 7 command bits + IrSender.sendRC5(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, 0, true); // 5 address, 7 command bits checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40); delay(DELAY_AFTER_SEND); #endif @@ -687,7 +699,7 @@ void loop() { Serial.println(F("Send RC6")); // RC6 check does not work stable without the flush Serial.flush(); - IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true); + IrSender.sendRC6(sAddress & 0xFF, sCommand, 0, true); checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); #endif @@ -706,7 +718,7 @@ void loop() { Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); - IrSender.write(&IRSendData, sRepeats); + IrSender.write(&IRSendData, 0); checkReceive(IRSendData.address & 0xFF, IRSendData.command); delay(DELAY_AFTER_SEND); #endif @@ -720,7 +732,7 @@ void loop() { Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); - IrSender.write(&IRSendData, sRepeats); + IrSender.write(&IRSendData, 0); checkReceive(IRSendData.address, IRSendData.command); delay(DELAY_AFTER_SEND); #endif @@ -730,7 +742,7 @@ void loop() { Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); - IrSender.write(&IRSendData, sRepeats); + IrSender.write(&IRSendData, 0); checkReceive(IRSendData.address & 0xFF, IRSendData.command); delay(DELAY_AFTER_SEND); #endif @@ -746,19 +758,21 @@ void loop() { #if defined(DECODE_BEO) Serial.println(F("Send Bang&Olufsen")); Serial.flush(); - IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, sRepeats); + IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0); # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) delay((RECORD_GAP_MICROS / 1000) + 1); + Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled. PrintRaw and try to decode")); IrReceiver.printIRResultRawFormatted(&Serial, true); - uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen; - IrReceiver.decodedIRData.rawDataPtr->rawlen = 6; + uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawlen; + IrReceiver.decodedIRData.rawlen = 6; // decode first part of frame IrReceiver.decode(); IrReceiver.printIRResultShort(&Serial); - // Remove trailing 6 entries for next decode - IrReceiver.decodedIRData.rawDataPtr->rawlen = tOriginalRawlen - 6; - for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawDataPtr->rawlen; ++i) { + // Remove trailing 6 entries for next decode try + Serial.println(F("- Remove trailing 6 entries for next decode try")); + IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; + for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6]; } # endif @@ -770,7 +784,7 @@ void loop() { IRSendData.protocol = BOSEWAVE; Serial.println(F("Send Bosewave with no address and 8 command bits")); Serial.flush(); - IrSender.write(&IRSendData, sRepeats); + IrSender.write(&IRSendData, 0); checkReceive(0, IRSendData.command & 0xFF); delay(DELAY_AFTER_SEND); #endif @@ -780,7 +794,7 @@ void loop() { Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); - IrSender.write(&IRSendData, sRepeats); + IrSender.write(&IRSendData, 0); checkReceive(0, IRSendData.command & 0xFF); delay(DELAY_AFTER_SEND); #endif @@ -813,7 +827,11 @@ void loop() { sAddress += 0x0101; sCommand += 0x11; s16BitCommand += 0x1111; - + sRepeats++; + // clip repeats at 4 + if (sRepeats > 4) { + sRepeats = 4; + } delay(DELAY_AFTER_LOOP); // additional delay at the end of each loop } diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index da30c2188..f19594994 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -12,7 +12,7 @@ address=0xFFF1 command=0x76 Send NEC with 8 bit address Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Send with: IrSender.sendNEC(0xF1, 0x76, ); -rawData[68]: +rawData[68]: -1044300 +8950,-4400 + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 @@ -29,7 +29,7 @@ Sum: 67650 Send NEC with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: +rawData[68]: -1055100 +8850,-4450 + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 @@ -46,7 +46,7 @@ Sum: 73150 Send NEC2 with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: +rawData[68]: -1055500 +8950,-4400 + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 @@ -63,7 +63,7 @@ Sum: 73400 Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first Send with: IrSender.sendNEC(0x80, 0x45, ); -rawData[68]: +rawData[68]: -1064450 +9050,-4450 + 550,- 550 + 600,- 550 + 600,- 600 + 550,- 600 @@ -80,7 +80,7 @@ Sum: 67800 Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format) Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first Send with: IrSender.sendNEC(0x4, 0x8, ); -rawData[68]: +rawData[68]: -1061400 +9000,-4400 + 600,- 500 + 650,- 500 + 600,-1650 + 600,- 500 @@ -97,7 +97,7 @@ Sum: 67900 Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102) Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first Send with: IrSender.sendOnkyo(0x102, 0x304, ); -rawData[68]: +rawData[68]: -1059700 +8900,-4400 + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500 @@ -114,7 +114,7 @@ Sum: 55450 Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3) Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first Send with: IrSender.sendNEC(0x102, 0x34, ); -rawData[68]: +rawData[68]: -1061500 +8950,-4400 + 600,- 500 + 550,-1700 + 600,- 500 + 650,- 500 @@ -131,7 +131,7 @@ Sum: 61000 Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: +rawData[100]: -1059500 +3450,-1700 + 450,- 450 + 450,-1250 + 450,- 400 + 450,- 450 @@ -150,10 +150,10 @@ rawData[100]: Sum: 54100 Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance - LSB first +- LSB first Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: +rawData[100]: -1076450 +3450,-1700 + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 @@ -171,10 +171,10 @@ rawData[100]: + 400 Sum: 53200 - MSB first +- MSB first Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: +rawData[100]: -1070700 +3400,-1700 + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 @@ -194,10 +194,10 @@ Sum: 53150 Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first -Send with: +Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A}; IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1650, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); -rawData[148]: +rawData[148]: -1076300 +8850,-4400 + 600,-1650 + 550,- 600 + 550,- 600 + 550,- 600 @@ -223,10 +223,10 @@ Sum: 138200 Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first -Send with: +Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[106]: +rawData[106]: -1115100 + 350,- 600 + 650,- 250 + 350,- 550 + 350,- 550 + 300,- 600 @@ -246,8 +246,8 @@ Sum: 47550 Send generic 32 bit PulseWidth 0x87654321 LSB first Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first -Send with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); -rawData[66]: +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); +rawData[66]: -1088600 + 950,- 550 + 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250 @@ -263,7 +263,7 @@ Sum: 24500 Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); -rawData[112]: +rawData[112]: -1089000 + 350,- 800 + 350,- 800 + 350,- 800 + 300,- 850 + 300,- 850 + 300,- 850 + 300,- 850 + 350,- 800 @@ -284,7 +284,7 @@ Sum: 63850 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); -rawData[68]: +rawData[68]: -1070700 +8900,-4550 + 500,-1600 + 650,- 500 + 600,- 500 + 600,- 550 @@ -301,7 +301,7 @@ Sum: 76500 Send Apple Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Send with: IrSender.sendApple(0xF1, 0x76, ); -rawData[68]: +rawData[68]: -1054650 +8950,-4400 + 600,- 550 + 550,-1650 + 650,-1600 + 600,-1600 @@ -318,7 +318,7 @@ Sum: 72100 Send Panasonic Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); -rawData[100]: +rawData[100]: -1054300 +3450,-1700 + 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450 @@ -339,7 +339,7 @@ Sum: 64400 Send Kaseikyo with 0x4711 as Vendor ID Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); -rawData[100]: +rawData[100]: -1074550 +3400,-1750 + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 450 @@ -360,7 +360,7 @@ Sum: 69500 Send Kaseikyo_Denon variant Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, ); -rawData[100]: +rawData[100]: -1067700 +3400,-1750 + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 400 @@ -381,7 +381,7 @@ Sum: 67700 Send Denon Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: +rawData[32]: -1073050 + 250,-1850 + 250,- 750 + 250,- 800 + 250,- 800 + 250,-1800 + 250,- 800 + 250,-1800 + 250,-1850 @@ -392,7 +392,7 @@ Sum: 23050 Send Denon/Sharp variant Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first Send with: IrSender.sendSharp(0x11, 0x76, ); -rawData[32]: +rawData[32]: -1018750 + 300,-1750 + 300,- 750 + 250,- 800 + 250,- 800 + 250,-1800 + 250,- 800 + 250,-1800 + 300,-1800 @@ -403,7 +403,7 @@ Sum: 24100 Send Sony/SIRCS with 7 command and 5 address bits Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: +rawData[26]: -1020950 +2400,- 650 + 550,- 600 +1200,- 550 +1250,- 550 + 650,- 550 @@ -414,7 +414,7 @@ Sum: 20950 Send Sony/SIRCS with 7 command and 8 address bits Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); -rawData[32]: +rawData[32]: -1032550 +2400,- 600 + 600,- 600 +1200,- 600 +1200,- 550 + 650,- 550 @@ -426,7 +426,7 @@ Sum: 26400 Send Sony/SIRCS with 7 command and 13 address bits Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20); -rawData[42]: +rawData[42]: -1036350 +2300,- 650 + 600,- 600 +1200,- 550 +1250,- 550 + 650,- 600 @@ -439,7 +439,7 @@ Sum: 35350 Send Samsung 8 bit command Protocol=Samsung Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x76, ); -rawData[68]: +rawData[68]: -1039650 +4400,-4450 + 550,-1700 + 550,- 550 + 600,- 550 + 550,- 550 @@ -456,7 +456,7 @@ Sum: 68750 Send Samsung 16 bit command Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: +rawData[68]: -1056350 +4400,-4400 + 600,-1650 + 550,- 550 + 600,- 550 + 550,- 550 @@ -473,7 +473,7 @@ Sum: 68650 Send Samsung48 16 bit command Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); -rawData[100]: +rawData[100]: -1056750 +4450,-4450 + 600,-1650 + 600,- 500 + 600,- 550 + 550,- 550 @@ -494,7 +494,7 @@ Sum: 95650 Send RC5 Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x36, ); -rawData[20]: +rawData[20]: -1073300 + 900,- 900 +1750,-1800 +1750,- 900 + 900,- 850 + 900,-1750 @@ -505,7 +505,7 @@ Sum: 23100 Send RC5X with 7.th MSB of command set Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x76, ); -rawData[20]: +rawData[20]: -1031250 +1800,-1750 + 850,- 900 +1800,- 850 + 900,- 900 + 900,-1750 @@ -516,7 +516,7 @@ Sum: 23050 Send RC6 Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Send with: IrSender.sendRC6(0xF1, 0x76, ); -rawData[36]: +rawData[36]: -1028550 +2650,- 900 + 450,- 900 + 450,- 450 + 450,- 450 + 450,- 850 @@ -529,7 +529,7 @@ Sum: 23250 Send JVC Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first Send with: IrSender.sendJVC(0xF1, 0x76, ); -rawData[36]: +rawData[36]: -1037050 +8400,-4150 + 500,-1600 + 550,- 500 + 500,- 550 + 550,- 500 @@ -542,7 +542,7 @@ Sum: 40400 Send Samsung Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: +rawData[68]: -1036350 +4450,-4400 + 550,-1700 + 600,- 550 + 550,- 550 + 600,- 550 @@ -559,7 +559,7 @@ Sum: 68750 Send LG Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first Send with: IrSender.sendLG(0xF1, 0x9876, ); -rawData[60]: +rawData[60]: -1054900 +9000,-4150 + 450,-1600 + 500,-1550 + 500,-1550 + 500,-1600 @@ -575,7 +575,7 @@ Sum: 59350 Send MagiQuest Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: +rawData[112]: -1049950 + 250,- 850 + 250,- 900 + 250,- 900 + 250,- 900 + 250,- 900 + 300,- 850 + 250,- 900 + 250,- 900 @@ -594,9 +594,29 @@ rawData[112]: Sum: 63750 Send Bang&Olufsen +- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled. PrintRaw and try to decode +rawData[112]: + -1049800 + + 300,-2900 + 200,-2850 + 250,-15200 + 300,-2850 + + 250,-9000 + 300,-5900 + 300,-5950 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-5950 + 250,-9000 + + 300,-2850 + 250,-9050 + 250,-5900 + 300,-5950 + + 250,-2850 + 250,-9000 + 300,-5950 + 250,-2850 + + 250,-12100 + 300,- 800 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 + + 350,- 800 + 350,- 800 + 650,- 500 + 350,- 800 + + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 500 + 350,- 850 + + 350,- 800 + 350,- 750 + 650,- 500 + 650,- 500 + + 300,- 850 + 650,- 500 + 650,- 500 + 650 +Sum: 176100 +Protocol=UNKNOWN Hash=0x643E0496 22 bits (incl. gap and start) received +- Remove trailing 6 entries for next decode try Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, ); -rawData[44]: +rawData[44]: -1078450 + 150,-2850 + 200,-2900 + 200,-15300 + 200,-2900 + 200,-9100 @@ -610,7 +630,7 @@ Sum: 136500 Send Bosewave with no address and 8 command bits Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Send with: IrSender.sendBoseWave(0x0, 0x76, ); -rawData[36]: +rawData[36]: -1044750 +1050,-1450 + 550,- 450 + 550,-1400 + 550,-1450 + 550,- 450 @@ -623,7 +643,7 @@ Sum: 26750 Send FAST Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Send with: IrSender.sendFAST(0x0, 0x76, ); -rawData[36]: +rawData[36]: -1036750 +2100,-1050 + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 @@ -636,7 +656,7 @@ Sum: 28900 Force buffer overflow by sending 280 marks and spaces Overflow Try to increase the "RAW_BUFFER_LENGTH" value of 150 in ../src/UnitTest.cpp -rawData[150]: +rawData[150]: -1040000 + 250,- 500 + 200,- 600 + 200,- 550 + 200,- 500 + 200,- 550 @@ -667,7 +687,7 @@ address=0xF2 command=0x87 Send NEC with 8 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -3276750 +8850,-4500 + 550,- 500 + 600,-1650 + 600,- 500 + 600,- 550 @@ -681,10 +701,27 @@ rawData[68]: + 600 Sum: 67600 +Repeat NEC frame for NEC2 +Protocol=NEC2 Address=0xF8 Command=0xED Repeat gap=48600us Raw-Data=0x12ED07F8 32 bits LSB first +!Use the NEC2 protocol for sending! +rawData[68]: + -87300 + +8950,-4400 + + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,- 500 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Sum: 67850 + Send NEC with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -998700 +8900,-4400 + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500 @@ -701,7 +738,7 @@ Sum: 67650 Send NEC2 with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -1055100 +8950,-4400 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 @@ -718,7 +755,7 @@ Sum: 67800 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Send with: IrSender.sendOnkyo(0xF2, 0x8887, ); -rawData[68]: +rawData[68]: -1053400 +8850,-4400 + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550 @@ -735,7 +772,7 @@ Sum: 62050 Send Apple Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Send with: IrSender.sendApple(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -1054100 +8900,-4450 + 550,- 550 + 600,-1650 + 600,-1650 + 600,-1650 diff --git a/library.json b/library.json index 611a73487..0bf219620 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/z3t0/Arduino-IRremote.git" }, - "version": "4.2.1", + "version": "4.3.0", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index b4a21a1ad..cc6e5e957 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.2.1 +version=4.3.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. NEW: TinyReceiver 2.0 and minor fixes. +paragraph=Currently included protocols: Denon / Sharp, JVC, LG / LG2, NEC / Onkyo / Apple, Panasonic / Kaseikyo, RC5, RC6, Samsung, Sony, (Pronto), BangOlufsen, BoseWave, Lego, Whynter, FAST, MagiQuest, Universal Pulse Distance and Pulse Width. NEW: TinyRSender improvements, sendSamsung bug fixes, new fields rawlen and initialGap and new functions stop/startTimer...(). category=Communication url=https://github.com/Arduino-IRremote/Arduino-IRremote architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 42d3e2cb2..c4368364b 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -58,8 +58,8 @@ typedef enum { RC5, RC6, SAMSUNG, + SAMSUNGLG, SAMSUNG48, - SAMSUNG_LG, SHARP, SONY, /* Now the exotic protocols */ @@ -71,7 +71,6 @@ typedef enum { FAST } decode_type_t; - #define SIRCS_12_PROTOCOL 12 #define SIRCS_15_PROTOCOL 15 #define SIRCS_20_PROTOCOL 20 @@ -95,6 +94,7 @@ struct DistanceWidthTimingInfoStruct { #define IRDATA_FLAGS_TOGGLE_BIT 0x08 ///< Is set if RC5 or RC6 toggle bit is set. #define IRDATA_TOGGLE_BIT_MASK 0x08 ///< deprecated -is set if RC5 or RC6 toggle bit is set. #define IRDATA_FLAGS_EXTRA_INFO 0x10 ///< There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID, or in decodedRawDataArray). +#define IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT 0x20 ///< Here we have a repeat of type NEC2 or SamsungLG #define IRDATA_FLAGS_WAS_OVERFLOW 0x40 ///< irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag. #define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Value is mainly determined by the (known) protocol. #define IRDATA_FLAGS_IS_LSB_FIRST 0x00 @@ -117,6 +117,15 @@ struct IRData { #endif uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above + + //These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0. +#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR + uint_fast8_t rawlen; ///< counter of entries in rawbuf +#else + uint_fast16_t rawlen; ///< counter of entries in rawbuf +#endif + uint16_t initialGap; ///< rawbuf[0] contains the initial gap of the last frame. + irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR. }; diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index c47d9db2b..20c7c8eb0 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -63,8 +63,8 @@ const char string_Kaseikyo_Mitsubishi[] PROGMEM = "Kaseikyo_Mitsubishi"; const char string_RC5[] PROGMEM = "RC5"; const char string_RC6[] PROGMEM = "RC6"; const char string_Samsung[] PROGMEM = "Samsung"; -const char string_Samsung48[] PROGMEM = "Samsung48"; const char string_SamsungLG[] PROGMEM = "SamsungLG"; +const char string_Samsung48[] PROGMEM = "Samsung48"; const char string_Sharp[] PROGMEM = "Sharp"; const char string_Sony[] PROGMEM = "Sony"; const char string_BangOlufsen[] PROGMEM = "Bang&Olufsen"; @@ -80,7 +80,7 @@ const char string_FAST[] PROGMEM = "FAST"; const char *const ProtocolNames[] PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, string_LG2, string_NEC, string_NEC2, string_Onkyo, string_Panasonic, string_Kaseikyo, string_Kaseikyo_Denon, string_Kaseikyo_Sharp, - string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_Samsung48, string_SamsungLG, + string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_SamsungLG, string_Samsung48, string_Sharp, string_Sony #if !defined(EXCLUDE_EXOTIC_PROTOCOLS) , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST @@ -178,7 +178,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap #endif #if !defined(DISABLE_CODE_FOR_RECEIVER) aSerial->print(' '); - aSerial->print((aIRDataPtr->rawDataPtr->rawlen + 1) / 2, DEC); + aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC); aSerial->println(F(" bits (incl. gap and start) received")); #endif } else { @@ -218,7 +218,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap #if !defined(DISABLE_CODE_FOR_RECEIVER) if (aPrintRepeatGap) { aSerial->print(F(" gap=")); - aSerial->print((uint32_t) aIRDataPtr->rawDataPtr->rawbuf[0] * MICROS_PER_TICK); + aSerial->print((uint32_t) aIRDataPtr->initialGap * MICROS_PER_TICK); aSerial->print(F("us")); } #else diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 3f92f890b..08f23cf11 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -342,6 +342,19 @@ void IRrecv::start() { pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif } + +/* + * Do not resume() reading of IR data + */ +void IRrecv::restartTimer() { + // Setup for cyclic 50 us interrupt + timerConfigForReceive(); // no interrupts enabled here! + // Timer interrupt is enabled after state machine reset + timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us. +#ifdef _IR_MEASURE_TIMING + pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); +#endif +} /** * Alias for start(). */ @@ -358,10 +371,18 @@ void IRrecv::start(uint32_t aMicrosecondsToAddToGapCounter) { irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK; start(); } +void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) { + irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK; + restartTimer(); +} void IRrecv::startWithTicksToAdd(uint16_t aTicksToAddToGapCounter) { irparams.TickCounterForISR += aTicksToAddToGapCounter; start(); } +void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) { + irparams.TickCounterForISR += aTicksToAddToGapCounter; + restartTimer(); +} void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) { irparams.TickCounterForISR += aTicksToAddToInternalTickCounter; @@ -385,6 +406,10 @@ void IRrecv::restartAfterSend() { void IRrecv::stop() { timerDisableReceiveInterrupt(); } + +void IRrecv::stopTimer() { + timerDisableReceiveInterrupt(); +} /** * Alias for stop(). */ @@ -408,7 +433,7 @@ bool IRrecv::isIdle() { /** * Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame. - * Counting of gap timing is independent of StateForISR and therefore independent of call time of resume(). + * Internal counting of gap timing is independent of StateForISR and therefore independent of call time of resume(). */ void IRrecv::resume() { // This check allows to call resume at arbitrary places or more than once @@ -434,11 +459,16 @@ void IRrecv::initDecodedIRData() { } else { decodedIRData.flags = IRDATA_FLAGS_EMPTY; // save last protocol, command and address for repeat handling (where they are compared or copied back :-)) - lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC and LG), so we must keep the original one + lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC, Samsung and LG), so we must keep the original one lastDecodedCommand = decodedIRData.command; lastDecodedAddress = decodedIRData.address; } + + //These 2 variables allow to call resume() directly after decode, if no dump is required. since 4.3.0. + decodedIRData.initialGap = decodedIRData.rawDataPtr->rawbuf[0]; + decodedIRData.rawlen = decodedIRData.rawDataPtr->rawlen; + decodedIRData.protocol = UNKNOWN; decodedIRData.command = 0; decodedIRData.address = 0; @@ -834,7 +864,7 @@ void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBip uint_fast8_t IRrecv::getBiphaselevel() { uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK) - if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawDataPtr->rawlen) { + if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawlen) { return SPACE; // After end of recorded buffer, assume space. } @@ -917,7 +947,7 @@ bool IRrecv::decodeHash() { unsigned long hash = FNV_BASIS_32; // the result is the same no matter if we use a long or unsigned long variable // Require at least 6 samples to prevent triggering on noise - if (decodedIRData.rawDataPtr->rawlen < 6) { + if (decodedIRData.rawlen < 6) { return false; } #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR @@ -925,7 +955,7 @@ bool IRrecv::decodeHash() { #else unsigned int i; #endif - for (i = 1; (i + 2) < decodedIRData.rawDataPtr->rawlen; i++) { + for (i = 1; (i + 2) < decodedIRData.rawlen; i++) { uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]); // Add value into the hash hash = (hash * FNV_PRIME_32) ^ value; @@ -1114,10 +1144,10 @@ bool IRrecv::checkForRecordGapsMicros(Print *aSerial) { * is smaller than known value for protocols (Sony with around 24 ms) */ if (decodedIRData.protocol <= PULSE_DISTANCE - && decodedIRData.rawDataPtr->rawbuf[0] < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) { + && decodedIRData.initialGap < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) { aSerial->println(); aSerial->print(F("Space of ")); - aSerial->print(decodedIRData.rawDataPtr->rawbuf[0] * MICROS_PER_TICK); + aSerial->print(decodedIRData.initialGap * MICROS_PER_TICK); aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of ")); aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD); aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc..")); @@ -1234,7 +1264,7 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf uint32_t IRrecv::getTotalDurationOfRawData() { uint16_t tSumOfDurationTicks = 0; - for (uint_fast8_t i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) { + for (uint_fast8_t i = 1; i < decodedIRData.rawlen; i++) { tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i]; } return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK; @@ -1248,19 +1278,27 @@ 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_PROTOCOL_WITH_DIFFERENT_REPEAT) { + /* + * Here we have a repeat of type NEC2 or SamsungLG. -> Inform the user to use this and not the initial protocol for sending. + */ + Serial.print(F("!Use the ")); + Serial.print(getProtocolString()); + Serial.println(F(" protocol for sending!")); + } else { + if (decodedIRData.protocol != UNKNOWN + && (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) { #if defined(DECODE_DISTANCE_WIDTH) uint_fast8_t tNumberOfArrayData = 0; if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) { # if __INT_WIDTH__ < 32 - aSerial->print(F("Send on a 8 bit platform with:")); + aSerial->print(F("Send on a 8 bit platform with: ")); tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1; if(tNumberOfArrayData > 1) { aSerial->println(); aSerial->print(F(" uint32_t tRawData[]={0x")); # else - aSerial->print(F("Send on a 32 bit platform with:")); + aSerial->print(F("Send on a 32 bit platform with: ")); tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1; if(tNumberOfArrayData > 1) { aSerial->println(); @@ -1277,19 +1315,22 @@ void IRrecv::printIRSendUsage(Print *aSerial) { } } aSerial->println(F("};")); - aSerial->print(F(" ")); + aSerial->print(F(" ")); } + } else { + aSerial->print(F("Send with: ")); } - aSerial->print(F(" IrSender.send")); + aSerial->print(F("IrSender.send")); + #else - aSerial->print(F("Send with: IrSender.send")); + aSerial->print(F("Send with: IrSender.send")); #endif #if defined(DECODE_DISTANCE_WIDTH) if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) { #endif - aSerial->print(getProtocolString()); - aSerial->print(F("(0x")); + aSerial->print(getProtocolString()); + aSerial->print(F("(0x")); #if defined(DECODE_MAGIQUEST) if (decodedIRData.protocol == MAGIQUEST) { # if (__INT_WIDTH__ < 32) @@ -1301,20 +1342,20 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(decodedIRData.address, HEX); } #else - /* - * New decoders have address and command - */ - aSerial->print(decodedIRData.address, HEX); + /* + * New decoders have address and command + */ + aSerial->print(decodedIRData.address, HEX); #endif - aSerial->print(F(", 0x")); - aSerial->print(decodedIRData.command, HEX); - if (decodedIRData.protocol == SONY) { - aSerial->print(F(", 2, ")); - aSerial->print(decodedIRData.numberOfBits); - } else { - aSerial->print(F(", ")); - } + 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_DISTANCE_WIDTH) } else { @@ -1357,14 +1398,10 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(decodedIRData.extra, HEX); } #endif - aSerial->print(F(");")); - aSerial->println(); - } -#if defined(DECODE_DISTANCE_WIDTH) - else { - aSerial->print(F("Send with:")); + aSerial->print(F(");")); + aSerial->println(); + } } -#endif } /** @@ -1386,7 +1423,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { # endif #endif aSerial->print(' '); - aSerial->print((decodedIRData.rawDataPtr->rawlen + 1) / 2, DEC); + aSerial->print((decodedIRData.rawlen + 1) / 2, DEC); aSerial->println(F(" bits received")); } else { /* @@ -1419,7 +1456,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { */ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) { - uint8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Get it once here in order to print quite consistent data, even if ISR is running + uint8_t tRawlen = decodedIRData.rawlen; // Get it once here in order to print quite consistent data, even if ISR is running // Print Raw data aSerial->print(F("rawData[")); aSerial->print(tRawlen, DEC); @@ -1430,9 +1467,9 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI */ aSerial->print(F(" -")); if (aOutputMicrosecondsInsteadOfTicks) { - aSerial->println((uint32_t) decodedIRData.rawDataPtr->rawbuf[0] * MICROS_PER_TICK, DEC); + aSerial->println((uint32_t) decodedIRData.initialGap * MICROS_PER_TICK, DEC); } else { - aSerial->println(decodedIRData.rawDataPtr->rawbuf[0], DEC); + aSerial->println(decodedIRData.initialGap, DEC); } #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR uint_fast8_t i; @@ -1524,7 +1561,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr aSerial->print(F("uint8_t rawTicks[")); // variable type, array name } - aSerial->print(decodedIRData.rawDataPtr->rawlen - 1, DEC); // array size + aSerial->print(decodedIRData.rawlen - 1, DEC); // array size aSerial->print(F("] = {")); // Start declaration // Dump data @@ -1533,7 +1570,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr #else unsigned int i; #endif - for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) { + for (i = 1; i < decodedIRData.rawlen; i++) { uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK; if (i & 1) { @@ -1553,10 +1590,8 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; aSerial->print(tTicks); } - if (i + 1 < decodedIRData.rawDataPtr->rawlen) - aSerial->print(','); // ',' not required on last one - if (!(i & 1)) - aSerial->print(' '); + if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one + if (!(i & 1)) aSerial->print(' '); } // End declaration @@ -1585,9 +1620,9 @@ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) { #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR uint_fast8_t i; #else - unsigned int i; + unsigned int i; #endif - for (i = 1; i < decodedIRData.rawDataPtr->rawlen; i++) { + for (i = 1; i < decodedIRData.rawlen; i++) { uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK; if (i & 1) { // Mark diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 420bbade9..c72a954bf 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -220,7 +220,7 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) { } else if (tProtocol == SAMSUNG48) { sendSamsung48(tAddress, tCommand, aNumberOfRepeats); - } else if (tProtocol == SAMSUNG_LG) { + } else if (tProtocol == SAMSUNGLG) { sendSamsungLG(tAddress, tCommand, aNumberOfRepeats); } else if (tProtocol == SONY) { @@ -341,7 +341,7 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma } else if (aProtocol == SAMSUNG48) { sendSamsung48(aAddress, aCommand, aNumberOfRepeats); - } else if (aProtocol == SAMSUNG_LG) { + } else if (aProtocol == SAMSUNGLG) { sendSamsungLG(aAddress, aCommand, aNumberOfRepeats); } else if (aProtocol == SONY) { @@ -693,10 +693,14 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc if (aNumberOfRepeats < 0) { if (aProtocolConstants->SpecialSendRepeatFunction != NULL) { + /* + * Send only a special repeat and return + */ aProtocolConstants->SpecialSendRepeatFunction(); return; } else { - aNumberOfRepeats = 0; // send a plain frame as repeat + // Send only one plain frame (as repeat) + aNumberOfRepeats = 0; } } @@ -708,7 +712,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc unsigned long tStartOfFrameMillis = millis(); if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aProtocolConstants->SpecialSendRepeatFunction != NULL) { - // send special repeat + // send special repeat, if specified and we are not in the first loop aProtocolConstants->SpecialSendRepeatFunction(); } else { /* @@ -722,12 +726,12 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { + auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis; /* * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ - auto tFrameDurationMillis = millis() - tStartOfFrameMillis; - if (aProtocolConstants->RepeatPeriodMillis > tFrameDurationMillis) { - delay(aProtocolConstants->RepeatPeriodMillis - tFrameDurationMillis); + if (aProtocolConstants->RepeatPeriodMillis > tCurrentFrameDurationMillis) { + delay(aProtocolConstants->RepeatPeriodMillis - tCurrentFrameDurationMillis); } } } diff --git a/src/IRVersion.h b/src/IRVersion.h index 4750c6a43..486d10778 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.2.1" +#define VERSION_IRREMOTE "4.3.0" #define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 2 -#define VERSION_IRREMOTE_PATCH 1 +#define VERSION_IRREMOTE_MINOR 3 +#define VERSION_IRREMOTE_PATCH 0 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index a12a9f663..d8eaaff49 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -186,10 +186,13 @@ class IRrecv { */ void begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback = false, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN); + void restartTimer(); void start(); void enableIRIn(); // alias for start void start(uint32_t aMicrosecondsToAddToGapCounter); + void restartTimer(uint32_t aMicrosecondsToAddToGapCounter); void startWithTicksToAdd(uint16_t aTicksToAddToGapCounter); + void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter); void restartAfterSend(); void addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter); @@ -199,6 +202,7 @@ class IRrecv { IRData* read(); // returns decoded data // write is a method of class IRsend below // size_t write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats = NO_REPEATS); + void stopTimer(); void stop(); void disableIRIn(); // alias for stop void end(); // alias for stop @@ -314,7 +318,7 @@ class IRrecv { void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks); bool checkForRecordGapsMicros(Print *aSerial); - IRData decodedIRData; // New: decoded IR data for the application + IRData decodedIRData; // Decoded IR data for the application // Last decoded IR data for repeat detection and parity for Denon autorepeat decode_type_t lastDecodedProtocol; @@ -535,6 +539,7 @@ class IRsend { void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true); void sendSamsungLGRepeat(); void sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); + void sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNumberOfRepeats); void sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); // redirected to sendDenon diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 9fa34a024..2649d74c6 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -289,9 +289,9 @@ static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) bool IRrecv::decodeBangOlufsen() { #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) - if (decodedIRData.rawDataPtr->rawlen != 6 && decodedIRData.rawDataPtr->rawlen < 36) { // 16 bits minimum + if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 36) { // 16 bits minimum #else - if (decodedIRData.rawDataPtr->rawlen < 44) { // 16 bits minimum + if (decodedIRData.rawlen < 44) { // 16 bits minimum #endif return false; } @@ -307,15 +307,15 @@ bool IRrecv::decodeBangOlufsen() { uint8_t tBitNumber = 0; BEO_TRACE_PRINT(F("Pre gap: ")); - BEO_TRACE_PRINT(decodedIRData.rawDataPtr->rawbuf[0] * 50); + BEO_TRACE_PRINT(decodedIRData.initialGap * 50); BEO_TRACE_PRINT(F(" raw len: ")); - BEO_TRACE_PRINTLN(decodedIRData.rawDataPtr->rawlen); + BEO_TRACE_PRINTLN(decodedIRData.rawlen); #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) /* * Check if we have the AGC part of the first frame in a row */ - if (decodedIRData.rawDataPtr->rawlen == 6) { + if (decodedIRData.rawlen == 6) { if ((matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_IR_MARK) || matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_DATALINK_MARK)) && (matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK) @@ -329,7 +329,7 @@ bool IRrecv::decodeBangOlufsen() { /* * Check if leading gap is trailing bit of first frame */ - if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[0], BEO_PULSE_LENGTH_START_BIT)) { + if (!matchSpace(decodedIRData.initialGap, BEO_PULSE_LENGTH_START_BIT)) { BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_TRACE_PRINTLN(F(": Leading gap is wrong")); // Leading gap is trailing bit of first frame return false; // no B&O protocol @@ -348,9 +348,9 @@ bool IRrecv::decodeBangOlufsen() { } // skip first zero header bit - for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawDataPtr->rawlen; tRawBufferMarkIndex += 2) { + for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) { #else - for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawDataPtr->rawlen; tRawBufferMarkIndex += 2) { + for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) { #endif uint16_t markLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex]; @@ -426,7 +426,7 @@ bool IRrecv::decodeBangOlufsen() { break; } #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP) - if (tRawBufferMarkIndex >= decodedIRData.rawDataPtr->rawlen - 3) { // (rawlen - 3) is index of trailing bit mark + if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of trailing bit mark BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_DEBUG_PRINTLN(F(": End of buffer, but no trailing bit detected")); return false; @@ -467,7 +467,7 @@ bool IRrecv::decodeBangOlufsen() { /* * Check for last bit after decoding it */ - if (tRawBufferMarkIndex >= decodedIRData.rawDataPtr->rawlen - 3) { // (rawlen - 3) is index of last bit mark + if (tRawBufferMarkIndex >= decodedIRData.rawlen - 3) { // (rawlen - 3) is index of last bit mark BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_TRACE_PRINTLN(F(": Last bit reached")); break; diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index bac9dcce9..6ca549931 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -68,10 +68,10 @@ bool IRrecv::decodeBoseWave() { } // Check we have enough data +4 for initial gap, start bit mark and space + stop bit mark - if (decodedIRData.rawDataPtr->rawlen != (2 * BOSEWAVE_BITS) + 4) { + if (decodedIRData.rawlen != (2 * BOSEWAVE_BITS) + 4) { IR_DEBUG_PRINT(F("Bose: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 36")); return false; } diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index bfb48a6df..1029e262e 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -156,10 +156,10 @@ bool IRrecv::decodeDenon() { // we have no start bit, so check for the exact amount of data bits // Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark - if (decodedIRData.rawDataPtr->rawlen != (2 * DENON_BITS) + 2) { + if (decodedIRData.rawlen != (2 * DENON_BITS) + 2) { IR_DEBUG_PRINT(F("Denon: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 32")); return false; } @@ -189,7 +189,7 @@ bool IRrecv::decodeDenon() { decodedIRData.command &= 0xFF; // Check for (auto) repeat - if (decodedIRData.rawDataPtr->rawbuf[0] < ((DENON_AUTO_REPEAT_DISTANCE + (DENON_AUTO_REPEAT_DISTANCE / 4)) / MICROS_PER_TICK)) { + if (decodedIRData.initialGap < ((DENON_AUTO_REPEAT_DISTANCE + (DENON_AUTO_REPEAT_DISTANCE / 4)) / MICROS_PER_TICK)) { repeatCount++; if (repeatCount > 1) { // skip first auto repeat decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT; @@ -280,7 +280,7 @@ void IRsend::sendSharp(uint16_t aAddress, uint16_t aCommand) { bool IRrecv::decodeDenonOld(decode_results *aResults) { // Check we have the right amount of data - if (decodedIRData.rawDataPtr->rawlen != 1 + 2 + (2 * DENON_BITS) + 1) { + if (decodedIRData.rawlen != 1 + 2 + (2 * DENON_BITS) + 1) { return false; } diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 0908f1544..e5c0b4712 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -155,10 +155,10 @@ bool IRrecv::decodeDistanceWidth() { /* * Accept only protocols with at least 8 bits */ - if (decodedIRData.rawDataPtr->rawlen < (2 * 8) + 4) { + if (decodedIRData.rawlen < (2 * 8) + 4) { IR_DEBUG_PRINT(F("PULSE_DISTANCE_WIDTH: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is less than 20")); return false; } @@ -172,7 +172,7 @@ bool IRrecv::decodeDistanceWidth() { /* * Count number of mark durations up to 49 ticks. Skip leading start and trailing stop bit. */ - for (i = 3; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) { + for (i = 3; i < (uint_fast8_t) decodedIRData.rawlen - 2; i += 2) { auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (tDurationTicks < DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; // count duration if less than DURATION_ARRAY_SIZE (50) @@ -219,7 +219,7 @@ bool IRrecv::decodeDistanceWidth() { * Count number of space durations. Skip leading start and trailing stop bit. */ tIndexOfMaxDuration = 0; - for (i = 4; i < (uint_fast8_t) decodedIRData.rawDataPtr->rawlen - 2; i += 2) { + for (i = 4; i < (uint_fast8_t) decodedIRData.rawlen - 2; i += 2) { auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (tDurationTicks < DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; @@ -286,7 +286,7 @@ bool IRrecv::decodeDistanceWidth() { #endif uint8_t tStartIndex = 3; // skip leading start bit for decoding. - uint16_t tNumberOfBits = (decodedIRData.rawDataPtr->rawlen / 2) - 1; + uint16_t tNumberOfBits = (decodedIRData.rawlen / 2) - 1; if (tSpaceTicksLong > 0 && tMarkTicksLong == 0) { // For PULSE_DISTANCE a stop bit is mandatory, for PULSE_WIDTH it is not required! tNumberOfBits--; // Correct for stop bit diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index 09998ac0e..0a6543a10 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -96,13 +96,13 @@ void IRsend::sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats) { bool IRrecv::decodeFAST() { -// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size +// uint_fast8_t tRawlen = decodedIRData.rawlen; // Using a local variable does not improve code size // Check we have the right amount of data (36). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawDataPtr->rawlen != ((2 * FAST_BITS) + 4)) { + if (decodedIRData.rawlen != ((2 * FAST_BITS) + 4)) { IR_DEBUG_PRINT(F("FAST: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 36")); return false; } diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 24ef4fb47..6267fb0f6 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -118,26 +118,26 @@ void IRsend::sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe bool IRrecv::decodeJVC() { -// uint_fast8_t tRawlen = decodedIRData.rawDataPtr->rawlen; // Using a local variable does not improve code size +// uint_fast8_t tRawlen = decodedIRData.rawlen; // Using a local variable does not improve code size // Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark. // +4 is for first frame, +2 is for repeats - if (decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawDataPtr->rawlen != ((2 * JVC_BITS) + 4)) { + if (decodedIRData.rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawlen != ((2 * JVC_BITS) + 4)) { IR_DEBUG_PRINT(F("JVC: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 34 or 36")); return false; } - if (decodedIRData.rawDataPtr->rawlen == ((2 * JVC_BITS) + 2)) { + if (decodedIRData.rawlen == ((2 * JVC_BITS) + 2)) { /* * Check for repeat * Check leading space and first and last mark length */ - if (decodedIRData.rawDataPtr->rawbuf[0] < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK)) + if (decodedIRData.initialGap < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK)) && matchMark(decodedIRData.rawDataPtr->rawbuf[1], JVC_BIT_MARK) - && matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen - 1], JVC_BIT_MARK)) { + && matchMark(decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawlen - 1], JVC_BIT_MARK)) { /* * We have a repeat here, so do not check for start bit */ diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 90fe1ece9..fe61f63e1 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -200,10 +200,10 @@ bool IRrecv::decodeKaseikyo() { decode_type_t tProtocol; // Check we have enough data (96 + 4) 4 for initial gap, start bit mark and space + stop bit mark - if (decodedIRData.rawDataPtr->rawlen != ((2 * KASEIKYO_BITS) + 4)) { + if (decodedIRData.rawlen != ((2 * KASEIKYO_BITS) + 4)) { IR_DEBUG_PRINT(F("Kaseikyo: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 100")); return false; } diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 6990cff78..572838cf0 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2017-2023 Darryl Smith, Armin Joachimsmeyer + * Copyright (c) 2017-2024 Darryl Smith, Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -124,7 +124,7 @@ LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, (LG_REPEAT_PERI * Start of send and decode functions ************************************/ /* - * Send special LG2 repeat not used yet + * Send special LG2 repeat - not used internally */ void IRsend::sendLG2Repeat() { enableIROut (LG_KHZ); // 38 kHz @@ -184,30 +184,30 @@ bool IRrecv::decodeLG() { */ // Check we have the right amount of data (60). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawDataPtr->rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) { + if (decodedIRData.rawlen != ((2 * LG_BITS) + 4) && (decodedIRData.rawlen != 4)) { IR_DEBUG_PRINT(F("LG: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 60 or 4")); return false; } // Check header "mark" this must be done for repeat and data if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG_HEADER_MARK)) { - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) { + if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], LG2_HEADER_MARK)) { + tProtocol = LG2; + tHeaderSpace = LG2_HEADER_SPACE; + } else { #if defined(LOCAL_DEBUG) Serial.print(F("LG: ")); Serial.println(F("Header mark is wrong")); #endif - return false; - } else { - tProtocol = LG2; - tHeaderSpace = LG2_HEADER_SPACE; + return false; // neither LG nor LG2 header } } // Check for repeat - here we have another header space length - if (decodedIRData.rawDataPtr->rawlen == 4) { + if (decodedIRData.rawlen == 4) { if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], LG_REPEAT_HEADER_SPACE) && matchMark(decodedIRData.rawDataPtr->rawbuf[3], LG_BIT_MARK)) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_MSB_FIRST; diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 2f87be673..a7aba5f56 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -47,13 +47,13 @@ // https://oberguru.net/elektronik/ir/codes/lego_power_functions_train.lircd.conf // // To ensure correct detection of IR messages six 38 kHz cycles are transmitted as mark. -// Low bit consists of 6 cycles of IR and 10 “cycles” of pause, -// high bit of 6 cycles IR and 21 “cycles” of pause and start bit of 6 cycles IR and 39 “cycles” of pause. +// Low bit 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 +// High bit range 526 � 947 us +// Start/stop bit range 947 � 1579 us // If tm is the maximum message length (16ms) and Ch is the channel number, then -// The delay before transmitting the first message is: (4 – Ch)*tm +// The 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 @@ -186,7 +186,7 @@ bool IRrecv::decodeLegoPowerFunctions() { /* * Check for autorepeat (should happen 4 times for one press) */ - if (decodedIRData.rawDataPtr->rawbuf[0] < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) { + if (decodedIRData.initialGap < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) { decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT; } decodedIRData.address = tToggleEscapeChannel; diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index 6e82550bf..d3941cd70 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -151,10 +151,10 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) { bool IRrecv::decodeMagiQuest() { // Check we have the right amount of data, magnitude and ID bits and 8 start bits + 0 stop bit - if (decodedIRData.rawDataPtr->rawlen != (2 * MAGIQUEST_BITS)) { + if (decodedIRData.rawlen != (2 * MAGIQUEST_BITS)) { IR_DEBUG_PRINT(F("MagiQuest: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 112")); return false; } diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index a0627e68f..e51eda676 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -171,8 +171,7 @@ uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aComma /** * NEC Send frame and special repeats * There is NO delay after the last sent repeat! - * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space - * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). + * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendNEC(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth(&NECProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); @@ -237,10 +236,10 @@ bool IRrecv::decodeNEC() { * Next try the decode */ // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawDataPtr->rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 4)) { + if (decodedIRData.rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawlen != 4)) { IR_DEBUG_PRINT(F("NEC: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 68 or 4")); return false; } @@ -251,7 +250,7 @@ bool IRrecv::decodeNEC() { } // Check for repeat - here we have another header space length - if (decodedIRData.rawDataPtr->rawlen == 4) { + if (decodedIRData.rawlen == 4) { if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_REPEAT_HEADER_SPACE) && matchMark(decodedIRData.rawDataPtr->rawbuf[3], NEC_BIT_MARK)) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; @@ -328,6 +327,7 @@ bool IRrecv::decodeNEC() { checkForRepeatSpaceTicksAndSetFlag(NEC_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK); if (decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT) { decodedIRData.protocol = NEC2; + decodedIRData.flags |= IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT; } return true; } diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index 29fcf6c9d..cc5291b04 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -93,7 +93,7 @@ void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) { bool IRrecv::decodeWhynter() { // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawDataPtr->rawlen != (2 * WHYNTER_BITS) + 4) { + if (decodedIRData.rawlen != (2 * WHYNTER_BITS) + 4) { return false; } if (!checkHeader(&WhynterProtocolConstants)) { diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 948ab8924..6c7aefeb0 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -256,10 +256,10 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFreque aSerial->print(F("char prontoData[] = \"")); dumpNumber(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken); dumpNumber(aSerial, toFrequencyCode(aFrequencyHertz)); - dumpNumber(aSerial, (decodedIRData.rawDataPtr->rawlen + 1) / 2); + dumpNumber(aSerial, (decodedIRData.rawlen + 1) / 2); dumpNumber(aSerial, 0); uint16_t timebase = toTimebase(aFrequencyHertz); - compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, timebase); // skip leading space + compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space aSerial->println("\";"); } @@ -326,9 +326,9 @@ size_t IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) { size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken); size += dumpNumber(aString, toFrequencyCode(frequency)); - size += dumpNumber(aString, (decodedIRData.rawDataPtr->rawlen + 1) / 2); + size += dumpNumber(aString, (decodedIRData.rawlen + 1) / 2); size += dumpNumber(aString, 0); - size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawDataPtr->rawlen - 1, + size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space return size; diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 594bb079a..9c161242a 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -160,11 +160,11 @@ bool IRrecv::decodeRC5() { initBiphaselevel(1, RC5_UNIT); // Skip gap space // Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark. - if (decodedIRData.rawDataPtr->rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawDataPtr->rawlen) { + if (decodedIRData.rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawlen) { // no debug output, since this check is mainly to determine the received protocol IR_DEBUG_PRINT(F("RC5: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not between 9 and 15")); return false; } @@ -179,7 +179,7 @@ bool IRrecv::decodeRC5() { /* * Get data bits - MSB first */ - for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) { + for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) { // get next 2 levels and check for transition uint8_t tStartLevel = getBiphaselevel(); uint8_t tEndLevel = getBiphaselevel(); @@ -396,10 +396,10 @@ bool IRrecv::decodeRC6() { uint32_t tDecodedRawData = 0; // Check we have the right amount of data (). The +3 for initial gap, start bit mark and space - if (decodedIRData.rawDataPtr->rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawDataPtr->rawlen) { + if (decodedIRData.rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawlen) { IR_DEBUG_PRINT(F("RC6: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not between 15 and 25")); return false; } @@ -428,7 +428,7 @@ bool IRrecv::decodeRC6() { return false; } - for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawDataPtr->rawlen; tBitIndex++) { + for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) { uint8_t tStartLevel; // start level of coded bit uint8_t tEndLevel; // end level of coded bit diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index f2c256ae0..4bb12a4d5 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2017-2023 Darryl Smith, Armin Joachimsmeyer + * Copyright (c) 2017-2024 Darryl Smith, Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,7 +63,7 @@ Sum: 68750 */ /* - * Samsung repeat frame can be the original frame again or a special repeat frame, + * Samsung repeat frame can be the original frame again or a special short repeat frame, * then we call the protocol SamsungLG. They differ only in the handling of repeat, * so we can not decide for the first frame which protocol is used. */ @@ -101,8 +101,11 @@ struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, - (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat }; + (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL }; +struct PulseDistanceWidthProtocolConstants SamsungLGProtocolConstants = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, +SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, + (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat }; /************************************ * Start of send and decode functions ************************************/ @@ -122,7 +125,8 @@ void IRsend::sendSamsungLGRepeat() { } /** - * Static function for sending special repeat frame. + * Like above, but implemented as a static function + * Used for sending special repeat frame. * For use in ProtocolConstants. Saves up to 250 bytes compared to a member function. */ void sendSamsungLGSpecialRepeat() { @@ -150,30 +154,34 @@ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNu tRawData.UByte.MidHighByte = aCommand; tRawData.UByte.HighByte = ~aCommand; - sendPulseDistanceWidth(&SamsungProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats); + sendPulseDistanceWidth(&SamsungLGProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats); } /** * Here we send Samsung32 * If we get a command < 0x100, we send command and then ~command + * If we get an address < 0x100, we send address and then address again, this makes it flipper IRDB compatible * !!! Be aware, that this is flexible, but makes it impossible to send e.g. 0x0042 as 16 bit value!!! * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent */ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - // send 16 bit address LongUnion tSendValue; - tSendValue.UWords[0] = aAddress; + if (aAddress < 0x100) { + // This makes it flipper IRDB compatible + // https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 + // Duplicate address byte, if data is 8 bit and 8 bit inverted and address is 8bit + tSendValue.UBytes[1] = aAddress; + tSendValue.UBytes[0] = aAddress; + } else { + tSendValue.UWords[0] = aAddress; + } + if (aCommand < 0x100) { // Send 8 command bits and then 8 inverted command bits LSB first tSendValue.UBytes[2] = aCommand; tSendValue.UBytes[3] = ~aCommand; - if (aAddress < 0x100) { - // This makes it flipper IRDB compatible - // https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 - // Duplicate address byte, if data is 8 bit and 8 bit inverted and address is 8bit - tSendValue.UBytes[1] = aAddress; - } + } else { // Send 16 command bits tSendValue.UWords[1] = aCommand; @@ -182,6 +190,22 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } +/** + * Maybe no one needs it in the wild... + * As above, but we are able to send e.g. 0x0042 as 16 bit address + * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent + */ +void IRsend::sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { + + LongUnion tSendValue; + // send 16 bit address + tSendValue.UWords[0] = aAddress; + // Send 16 command bits + tSendValue.UWords[1] = aCommand; + + sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); +} + /** * Here we send Samsung48 * We send 2 x (8 bit command and then ~command) @@ -220,11 +244,11 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu bool IRrecv::decodeSamsung() { // Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark - if (decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG_BITS) + 4) - && decodedIRData.rawDataPtr->rawlen != ((2 * SAMSUNG48_BITS) + 4) && (decodedIRData.rawDataPtr->rawlen != 6)) { + if (decodedIRData.rawlen != ((2 * SAMSUNG_BITS) + 4) && decodedIRData.rawlen != ((2 * SAMSUNG48_BITS) + 4) + && (decodedIRData.rawlen != 6)) { IR_DEBUG_PRINT(F("Samsung: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 6 or 68 or 100")); return false; } @@ -234,11 +258,11 @@ bool IRrecv::decodeSamsung() { } // Check for SansungLG style repeat - if (decodedIRData.rawDataPtr->rawlen == 6) { - decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; + if (decodedIRData.rawlen == 6) { + decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; decodedIRData.command = lastDecodedCommand; - decodedIRData.protocol = SAMSUNG_LG; + decodedIRData.protocol = SAMSUNGLG; return true; } @@ -256,7 +280,7 @@ bool IRrecv::decodeSamsung() { tValue.ULong = decodedIRData.decodedRawData; decodedIRData.address = tValue.UWord.LowWord; - if (decodedIRData.rawDataPtr->rawlen == (2 * SAMSUNG48_BITS) + 4) { + if (decodedIRData.rawlen == (2 * SAMSUNG48_BITS) + 4) { /* * Samsung48 */ @@ -298,8 +322,9 @@ bool IRrecv::decodeSamsung() { * Samsung32 */ if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { - // 8 bit command protocol + // 8 bit command (and address) protocol decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit + decodedIRData.address = tValue.UByte.MidLowByte; // assume LowByte == MidLowByte } else { // 16 bit command protocol decodedIRData.command = tValue.UWord.HighWord; // first 16 bit diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index 591d58dcc..9f0d0c2ff 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -113,16 +113,16 @@ bool IRrecv::decodeSony() { } // Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42 - if (decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_MAX) + 2 - && decodedIRData.rawDataPtr->rawlen != (2 * SONY_BITS_15) + 2) { + if (decodedIRData.rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_MAX) + 2 + && decodedIRData.rawlen != (2 * SONY_BITS_15) + 2) { IR_DEBUG_PRINT(F("Sony: ")); IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawDataPtr->rawlen); + IR_DEBUG_PRINT(decodedIRData.rawlen); IR_DEBUG_PRINTLN(F(" is not 12, 15 or 20")); return false; } - if (!decodePulseDistanceWidthData(&SonyProtocolConstants, (decodedIRData.rawDataPtr->rawlen - 1) / 2, 3)) { + if (!decodePulseDistanceWidthData(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3)) { #if defined(LOCAL_DEBUG) Serial.print(F("Sony: ")); Serial.println(F("Decode failed")); @@ -134,7 +134,7 @@ bool IRrecv::decodeSony() { // decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value decodedIRData.command = decodedIRData.decodedRawData & 0x7F; // first 7 bits decodedIRData.address = decodedIRData.decodedRawData >> 7; // next 5 or 8 or 13 bits - decodedIRData.numberOfBits = (decodedIRData.rawDataPtr->rawlen - 1) / 2; + decodedIRData.numberOfBits = (decodedIRData.rawlen - 1) / 2; decodedIRData.protocol = SONY; //Check for repeat From f2838859e05302309513f0d6b7665a3cc104e353 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 25 Feb 2024 23:18:27 +0100 Subject: [PATCH 031/133] Added Hob2Hood protocol --- README.md | 3 + changelog.md | 1 + .../PinDefinitionsAndMore.h | 345 ++++++++++++++++++ .../ReceiveAndSendHob2Hood.ino | 143 ++++++++ src/IRReceive.hpp | 10 +- src/IRSend.hpp | 23 +- 6 files changed, 518 insertions(+), 7 deletions(-) create mode 100644 examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h create mode 100644 examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino diff --git a/README.md b/README.md index c011d481d..3f80d4042 100644 --- a/README.md +++ b/README.md @@ -660,6 +660,9 @@ The file *acLG.h* contains the command documentation of the LG air conditioner I IReceiverTimingAnalysis can be tested online with [WOKWI](https://wokwi.com/projects/299033930562011656) Click on the receiver while simulation is running to specify individual IR codes. +#### ReceiveAndSendHob2Hood +[Example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendLGAirConditionerDemo/ReceiveAndSendHobToHood.ino) for receiving and sending AEG / Elektrolux Hob2Hood protocol.
+ #### ReceiverTimingAnalysis This [example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino) analyzes the signal delivered by your IR receiver module. Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.
diff --git a/changelog.md b/changelog.md index 19d5d704f..832c2b336 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Fixed sendSamsung() / sendSamsungLG() bug. - Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). - Added rawlen and initialGap to IRData. +- Added ReceiveAndSendHobToHood example. # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h new file mode 100644 index 000000000..54395f68e --- /dev/null +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -0,0 +1,345 @@ +/* + * 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 + * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore + * ATtiny1604 2 3|PA5 % + * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore + * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore + * SAMD21 3 4 5 + * ESP8266 14|D5 12|D6 % + * ESP32 15 4 27 + * BluePill PA6 PA7 PA3 + * APOLLO3 11 12 5 + * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 + */ +//#define _IR_MEASURE_TIMING // For debugging purposes. + +#if defined(__AVR__) +#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. +#define IR_RECEIVE_PIN PIN_PB0 +#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. +#define TONE_PIN PIN_PB3 +#define _IR_TIMING_TEST_PIN PIN_PB3 + +# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" +// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. +# if defined(ARDUINO_AVR_DIGISPARKPRO) +// For use with Digispark original core +#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 +//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 +#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 +#define _IR_TIMING_TEST_PIN 10 // PA4 +# else +// For use with ATTinyCore +#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 +#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 +# endif + +# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +#define IR_RECEIVE_PIN PIN_PB2 // INT0 +#define IR_SEND_PIN PIN_PA4 +#define TONE_PIN PIN_PA3 +#define _IR_TIMING_TEST_PIN PIN_PA5 + +# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +// Pin 6 is TX, pin 7 is RX +#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 +#define IR_SEND_PIN PIN_PD4 // 4 +#define TONE_PIN PIN_PB1 // 9 +#define _IR_TIMING_TEST_PIN PIN_PB0 // 8 + +# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore +// Tiny Core Dev board +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 +#define IR_SEND_PIN PIN_PA2 // 19 +#define TONE_PIN PIN_PA3 // 20 +#define APPLICATION_PIN PIN_PA0 // 0 +#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 + +# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 14 +#define IR_SEND_PIN PIN_PA1 // 16 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 +#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output +#define LED_BUILTIN PIN_PB5 // 4 + +# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA3 // 10 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN PIN_PA7 // 3 +#define APPLICATION_PIN PIN_PB2 // 5 + +#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ +|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ +|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ +|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ +|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ +|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ +|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ +|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ +|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 13 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. +#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit +// We have no built in LED at pin 13 -> reuse RX LED +#undef LED_BUILTIN +#define LED_BUILTIN LED_BUILTIN_RX +# endif +# endif // defined(__AVR_ATtiny25__)... + +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 +// To be compatible with Uno R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ESP8266) +#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW +#define IR_RECEIVE_PIN 14 // D5 +#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED +#define _IR_TIMING_TEST_PIN 2 // D4 +#define APPLICATION_PIN 13 // D7 + +#define tone(...) void() // tone() inhibits receive timer +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) +#define IR_RECEIVE_PIN 8 +#define IR_SEND_PIN 9 +#define TONE_PIN 10 // ADC2_0 +#define APPLICATION_PIN 11 + +#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 ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) +#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer. +void tone(uint8_t aPinNumber, unsigned int aFrequency){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); +} +void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); + delay(aDuration); + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +void noTone(uint8_t aPinNumber){ + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) + +#define IR_RECEIVE_PIN 15 // D15 +#define IR_SEND_PIN 4 // D4 +#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 +#define APPLICATION_PIN 16 // RX2 pin + +#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill +// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() +#define IR_RECEIVE_PIN PA6 +#define IR_RECEIVE_PIN_STRING "PA6" +#define IR_SEND_PIN PA7 +#define IR_SEND_PIN_STRING "PA7" +#define TONE_PIN PA3 +#define _IR_TIMING_TEST_PIN PA5 +#define APPLICATION_PIN PA2 +#define APPLICATION_PIN_STRING "PA2" +# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) +// BluePill LED is active low +#define FEEDBACK_LED_IS_ACTIVE_LOW +# endif + +#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards +#define IR_RECEIVE_PIN 11 +#define IR_SEND_PIN 12 +#define TONE_PIN 5 + +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico +#define IR_SEND_PIN 4 // GPIO16 +#define TONE_PIN 5 +#define APPLICATION_PIN 6 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 8 + +#elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico +#define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3) +#define IR_SEND_PIN 16 // GPIO16 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 20 + +// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN +// and use the external reset with 1 kOhm to ground to enter UF2 mode +#undef LED_BUILTIN +#define LED_BUILTIN 6 + +#elif defined(PARTICLE) // !!!UNTESTED!!! +#define IR_RECEIVE_PIN A4 +#define IR_SEND_PIN A5 // Particle supports multiple pins + +#define LED_BUILTIN D7 + +/* + * 4 times the same (default) layout for easy adaption in the future + */ +#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) +// On the Zero and others we switch explicitly to SerialUSB +#define Serial SerialUSB +#endif + +// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17. +// Attention!!! D2 and D4 are swapped on these boards!!! +// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 24 // PB11 +// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 25 // PB03 +//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW + +#elif defined (NRF51) // BBC micro:bit +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define APPLICATION_PIN 1 +#define _IR_TIMING_TEST_PIN 4 + +#define tone(...) void() // no tone() available +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#else +#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h. +// Default valued for unidentified boards +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 +#endif // defined(ESP8266) + +#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) +#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation +#else +# if defined(SEND_PWM_BY_TIMER) +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp +# endif +#endif + +#if !defined (FLASHEND) +#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined +#endif +#if !defined (RAMEND) +#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined +#endif + +/* + * Helper macro for getting a macro definition as string + */ +#if !defined(STR_HELPER) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino new file mode 100644 index 000000000..231aa9d2f --- /dev/null +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -0,0 +1,143 @@ +/* + * ReceiveAndSendHob2Hood.cpp + * + * Demonstrates receiving and sending of IR codes for AEG / Elektrolux Hob2Hood protocol + * + * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * + ************************************************************************************ + * MIT License + * + * Copyright (c) 2024 Armin Joachimsmeyer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************************ + */ + +#include + +#define DECODE_HASH // Only decoder, which works for Hob2Hood. protocol is UNKNOWN and only raw data is set. + +//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory +//#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. + +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include + +// IR commands from AEG hob2hood device +#define NUMBER_OF_HOB_TO_HOOD_COMMANDS 7 +#define HOB_TO_HOOD_HASH_CODE_FAN_1 0xE3C01BE2 +#define HOB_TO_HOOD_HASH_CODE_FAN_2 0xD051C301 +#define HOB_TO_HOOD_HASH_CODE_FAN_3 0xC22FFFD7 +#define HOB_TO_HOOD_HASH_CODE_FAN_4 0xB9121B29 +#define HOB_TO_HOOD_HASH_CODE_FAN_OFF 0x55303A3 +#define HOB_TO_HOOD_HASH_CODE_LIGHT_ON 0xE208293C +#define HOB_TO_HOOD_HASH_CODE_LIGHT_OFF 0x24ACF947 + +// based on https://pastebin.com/N6kG7Wu5 +#define HOB_TO_HOOD_UNIT_MICROS 725 +#define H2H_1 HOB_TO_HOOD_UNIT_MICROS +#define H2H_2 (HOB_TO_HOOD_UNIT_MICROS*2) // 1450 +#define H2H_3 (HOB_TO_HOOD_UNIT_MICROS*3) // 2175 +#define H2H_4 (HOB_TO_HOOD_UNIT_MICROS*4) // 2900 +#define H2H_5 (HOB_TO_HOOD_UNIT_MICROS*5) // 3625 + +// First entry is the length of the raw command +const uint16_t Fan1[] PROGMEM { 15, H2H_2, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1, +H2H_3, H2H_1 }; +const uint16_t Fan2[] PROGMEM { 9, H2H_2, H2H_2, H2H_1, H2H_4, H2H_1, H2H_3, H2H_5, H2H_3, H2H_3 }; +const uint16_t Fan3[] PROGMEM { 9, H2H_1, H2H_3, H2H_4, H2H_4, H2H_3, H2H_1, H2H_1, H2H_3, H2H_3 }; +const uint16_t Fan4[] PROGMEM { 13, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_2, H2H_1, H2H_3, H2H_1, H2H_1, H2H_2 }; +const uint16_t FanOff[] PROGMEM { 15, H2H_1, H2H_2, H2H_1, H2H_2, H2H_3, H2H_2, H2H_1, H2H_2, H2H_2, H2H_3, H2H_1, H2H_2, H2H_1, +H2H_1, H2H_1 }; +const uint16_t LightOn[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_1, H2H_1, H2H_2, H2H_4, H2H_1, +H2H_1, H2H_1, H2H_1, H2H_2 }; +const uint16_t LightOff[] PROGMEM { 17, H2H_1, H2H_2, H2H_1, H2H_1, H2H_1, H2H_1, H2H_1, H2H_3, H2H_1, H2H_1, H2H_1, H2H_2, H2H_1, +H2H_2, H2H_1, H2H_1, H2H_1 }; +const uint16_t *const Hob2HoodSendCommands[NUMBER_OF_HOB_TO_HOOD_COMMANDS] = { Fan1, Fan2, Fan3, Fan4, FanOff, LightOn, LightOff }; // Constant array in RAM + +void setup() { + Serial.begin(115200); +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! +#endif + // Just to know which program is running on my Arduino + Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); + + // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED + IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); + + Serial.print(F("Ready to receive Hob2Hood IR signals at pin " STR(IR_RECEIVE_PIN))); + IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + Serial.println(F("Send Hob2Hood IR signals at pin " STR(IR_SEND_PIN))); +} + +/* + * Send Hob2Hood protocol + */ +void loop() { + static long sLastMillisOfSend = 0; + static uint8_t sSendCommandIndex = 0; + + if (IrReceiver.decode()) { + IrReceiver.resume(); // Early enable receiving of the next IR frame + IrReceiver.printIRResultShort(&Serial); + + /* + * Finally, check the received data and perform actions according to the received command + */ + switch (IrReceiver.decodedIRData.decodedRawData) { + case HOB_TO_HOOD_HASH_CODE_FAN_OFF: + Serial.print(F("FAN off")); + break; + case HOB_TO_HOOD_HASH_CODE_FAN_1: + Serial.print(F("FAN 1")); + break; + case HOB_TO_HOOD_HASH_CODE_FAN_2: + Serial.print(F("FAN 2")); + break; + default: + Serial.print(F("unknown Hob2Hood IR command")); + break; + } + } + + /* + * Send next command every 5 seconds + */ + if (millis() - sLastMillisOfSend > 2000) { + sLastMillisOfSend = millis(); + +#if defined(__AVR__) + uint16_t tLengthOfRawCommand = pgm_read_word(Hob2HoodSendCommands[sSendCommandIndex]); // length is the 1. word in array +#else + uint16_t tLengthOfRawCommand = *Hob2HoodSendCommands[sSendCommandIndex]; // length is the 1. word in array +#endif + const uint16_t *tAddressOfRawCommandSequence = Hob2HoodSendCommands[sSendCommandIndex] + 1; // Raw sequence starts at the 2. word of array + Serial.print(F("Send Hob2Hood command index=")); + Serial.println(sSendCommandIndex); + IrSender.sendRaw_P(tAddressOfRawCommandSequence, tLengthOfRawCommand, 38); + + // Prepare for next command + sSendCommandIndex++; + if (sSendCommandIndex >= NUMBER_OF_HOB_TO_HOOD_COMMANDS) { + sSendCommandIndex = 0; + } + } +} diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 08f23cf11..452604db4 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -930,11 +930,10 @@ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) { * Instead of decoding using a standard encoding scheme * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. * - * The algorithm: look at the sequence of MARK signals, and see if each one - * is shorter (0), the same length (1), or longer (2) than the previous. - * Do the same with the SPACE signals. Hash the resulting sequence of 0's, - * 1's, and 2's to a 32-bit value. This will give a unique value for each - * different code (probably), for most code systems. + * The algorithm: look at the sequence of MARK and SPACE signals, and see if each one + * is shorter (0), the same length (1), or longer (2) than the previous MARK or SPACE. + * Hash the resulting sequence of 0's, 1's, and 2's to a 32-bit value. + * This will give a unique value for each different code (probably), for most code systems. * * Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param * Converts the raw code values into a 32-bit hash code. @@ -956,6 +955,7 @@ bool IRrecv::decodeHash() { unsigned int i; #endif for (i = 1; (i + 2) < decodedIRData.rawlen; i++) { + // Compare mark with mark and space with space uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]); // Add value into the hash hash = (hash * FNV_PRIME_32) ^ value; diff --git a/src/IRSend.hpp b/src/IRSend.hpp index c72a954bf..00363a300 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -466,15 +466,24 @@ void IRsend::sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast16_t a if (i & 1) { // Odd space(duration); +# if defined(LOCAL_DEBUG) + Serial.print(F("S=")); +# endif } else { mark(duration); +# if defined(LOCAL_DEBUG) + Serial.print(F("M=")); +# endif } +# if defined(LOCAL_DEBUG) + Serial.println(duration); +# endif } #endif } /** - * New function using an 8 byte tick timing array in FLASH to save program memory + * New function using an 8 byte tick (50 us) timing array in FLASH to save program memory * Raw data starts with a Mark. No leading space as in received timing data! */ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz) { @@ -484,16 +493,26 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf // Set IR carrier frequency enableIROut(aIRFrequencyKilohertz); + uint_fast16_t duration; for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) { - uint_fast16_t duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK; + duration = pgm_read_byte(&aBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK; if (i & 1) { // Odd space(duration); +# if defined(LOCAL_DEBUG) + Serial.print(F("S=")); +# endif } else { mark(duration); +# if defined(LOCAL_DEBUG) + Serial.print(F("M=")); +# endif } } IRLedOff(); // Always end with the LED off +# if defined(LOCAL_DEBUG) + Serial.println(duration); +# endif #endif } From 29564e83e12e5851cc558342eccb8162c2f17819 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 27 Feb 2024 09:55:39 +0100 Subject: [PATCH 032/133] Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). --- changelog.md | 1 + .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 23 ++++++++++++------- examples/MicroGirs/MicroGirs.ino | 2 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 +- .../ReceiveAndSendDistanceWidth.ino | 2 +- .../ReceiveAndSendHob2Hood.ino | 2 +- examples/ReceiveDump/ReceiveDump.ino | 2 +- .../ReceiveOneAndSendMultiple.ino | 2 +- examples/SendAndReceive/SendAndReceive.ino | 2 +- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 2 +- examples/SendDemo/SendDemo.ino | 2 +- .../SendLGAirConditionerDemo.ino | 2 +- examples/SendProntoDemo/SendProntoDemo.ino | 2 +- examples/SendRawDemo/SendRawDemo.ino | 2 +- examples/SimpleSender/SimpleSender.ino | 4 ++-- examples/UnitTest/UnitTest.ino | 2 +- src/IRremoteInt.h | 11 +++++++-- 17 files changed, 40 insertions(+), 25 deletions(-) diff --git a/changelog.md b/changelog.md index 832c2b336..089c9c12a 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). - Added rawlen and initialGap to IRData. - Added ReceiveAndSendHobToHood example. +- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 1b420c53f..808ab666d 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -354,18 +354,25 @@ void printIRResultOnLCD() { if (IrReceiver.decodedIRData.protocol == UNKNOWN) { /* - * Print number of bits received and microseconds of signal + * Print number of bits received and hash code or microseconds of signal */ myLCD.setCursor(0, 1); uint8_t tNumberOfBits = (IrReceiver.decodedIRData.rawDataPtr->rawlen + 1) / 2; - if (tNumberOfBits < 10) { - myLCD.print(' '); // padding space - } - myLCD.print(tNumberOfBits); + uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits); myLCD.print(F(" bit ")); - uint_fast8_t tDurationStringLength = myLCD.print(IrReceiver.getTotalDurationOfRawData()); - myLCD.print(F(" \xE4s")); // \xE4 is micro symbol - printSpacesOnLCD(7 - tDurationStringLength); + + if (IrReceiver.decodedIRData.decodedRawData != 0) { + if (tNumberOfBits < 10) { + myLCD.print('0'); + tPrintedStringLength++; + } + myLCD.print('x'); + tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX) + 1; + } else { + tPrintedStringLength += myLCD.print(IrReceiver.getTotalDurationOfRawData()); + myLCD.print(F(" \xE4s")); // \xE4 is micro symbol + } + printSpacesOnLCD(11 - tPrintedStringLength); sLastProtocolAddress = 4711; sLastCommand = 44711; diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index a840bf240..52e6c3a8c 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -317,7 +317,7 @@ void setup() { #endif #if defined(IR_SEND_PIN) - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin #else IrSender.begin(3, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN); // Specify send pin and enable feedback LED at default feedback LED pin #endif diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index fdd4eaf36..f763be284 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -127,7 +127,7 @@ void setup() { printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin ")); Serial.println(SEND_BUTTON_PIN); } diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 5c2e73556..c9ded9475 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -99,7 +99,7 @@ void setup() { IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); Serial.println(F("Ready to receive pulse distance/width coded IR signals at pin " STR(IR_RECEIVE_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.print(F("Ready to send IR signals at pin " STR(IR_SEND_PIN) " on press of button at pin ")); Serial.println(SEND_BUTTON_PIN); } diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index 231aa9d2f..9bb6113c3 100644 --- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -84,7 +84,7 @@ 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 as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.println(F("Send Hob2Hood IR signals at pin " STR(IR_SEND_PIN))); } diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index eb30f5b07..93efcfca4 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -88,7 +88,7 @@ void setup() { Serial.println(); Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!")); Serial.println(); - Serial.println(F("If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2, SamsungLG or LG2, which is determined by the repeats")); + Serial.println(F("If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2 or SamsungLG, which is determined by the repeats")); Serial.println(); } diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index c59fa770e..33218ab85 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -123,7 +123,7 @@ void setup() { printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.println(F("Ready to send IR signals at pin " STR(IR_SEND_PIN))); } diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 7303c1afc..8eb75ab3b 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -65,7 +65,7 @@ void setup() { Serial.print(F("Ready to receive IR signals of protocols: ")); printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604 diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 60197cc2f..7cf97edca 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -111,7 +111,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); #if defined(IR_SEND_PIN) - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); #else uint8_t tSendPin = 3; diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 27dc4696e..1a23cd4cf 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -58,7 +58,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); #if defined(IR_SEND_PIN) - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin # if defined(IR_SEND_PIN_STRING) Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING)); # else diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index 9697745e1..3b8ac4690 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -75,7 +75,7 @@ delay(4000); // To be able to connect Serial monitor after reset or power up and /* * The IR library setup. That's all! */ - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin Serial.println(); diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index ba92eff21..6096a9b70 100644 --- a/examples/SendProntoDemo/SendProntoDemo.ino +++ b/examples/SendProntoDemo/SendProntoDemo.ino @@ -64,7 +64,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin } void loop() { diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 351148ada..77ea3cc8a 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -58,7 +58,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin } /* diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index 0ea7ece3c..a1e2515d3 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -36,8 +36,8 @@ void setup() { /* * The IR library setup. That's all! */ -// IrSender.begin(); // Start with IR_SEND_PIN as send pin and if NO_LED_FEEDBACK_CODE is NOT defined, enable feedback LED at default feedback LED pin - IrSender.begin(DISABLE_LED_FEEDBACK); // Start with IR_SEND_PIN as send pin and disable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin + disableLEDFeedback(); // Disable feedback LED at default feedback LED pin } /* diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index ce00030ef..0a254165a 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -138,7 +138,7 @@ void setup() { #endif #if defined(IR_SEND_PIN) - IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin + IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin # if defined(IR_SEND_PIN_STRING) Serial.println(F("at pin " IR_SEND_PIN_STRING)); # else diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index d8eaaff49..c39fca9fc 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -425,11 +425,18 @@ class IRsend { */ #if defined(IR_SEND_PIN) void begin(); - void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN); + // The default parameter allowed to specify IrSender.begin(7); without errors, if IR_SEND_PIN was defined. But the semantics is not the one the user expect. + void begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin); // 4.3.1 Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter + // The next function is a dummy to avoid acceptance of pre 4.3 calls to begin(DISABLE_LED_FEEDBACK); + void begin(uint8_t aSendPin) +# if !defined (DOXYGEN) + __attribute__ ((deprecated ("Error: IR_SEND_PIN is still defined, therefore the function begin(aSendPin) is NOT available. You must disable '#define IR_SEND_PIN' to enable this function."))); +# endif + // The next function is a dummy to avoid acceptance of pre 4.0 calls to begin(IR_SEND_PIN, DISABLE_LED_FEEDBACK); void begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback) # if !defined (DOXYGEN) - __attribute__ ((deprecated ("You must use begin(ENABLE_LED_FEEDBACK) or begin(DISABLE_LED_FEEDBACK) since version 4.0."))); + __attribute__ ((deprecated ("You must use begin() and enableLEDFeedback() or disableLEDFeedback() since version 4.3."))); # endif #else IRsend(uint_fast8_t aSendPin); From 8558db8b74f322bb1567c7c6653bc676aa38067e Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 29 Feb 2024 02:05:55 +0100 Subject: [PATCH 033/133] ESP32-C3 modifications --- .github/workflows/LibraryBuild.yml | 8 ++++ README.md | 9 +++-- changelog.md | 3 +- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 12 +++--- examples/ControlRelay/PinDefinitionsAndMore.h | 12 +++--- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 12 +++--- .../PinDefinitionsAndMore.h | 12 +++--- examples/MicroGirs/PinDefinitionsAndMore.h | 12 +++--- .../ReceiveAndSend/PinDefinitionsAndMore.h | 12 +++--- .../PinDefinitionsAndMore.h | 12 +++--- .../PinDefinitionsAndMore.h | 12 +++--- examples/ReceiveDemo/PinDefinitionsAndMore.h | 12 +++--- examples/ReceiveDump/PinDefinitionsAndMore.h | 12 +++--- .../PinDefinitionsAndMore.h | 12 +++--- .../SendAndReceive/PinDefinitionsAndMore.h | 12 +++--- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 12 +++--- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 4 +- examples/SendDemo/PinDefinitionsAndMore.h | 12 +++--- examples/SendDemo/SendDemo.ino | 8 +++- .../PinDefinitionsAndMore.h | 12 +++--- .../SendLGAirConditionerDemo.ino | 4 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 12 +++--- examples/SendProntoDemo/SendProntoDemo.ino | 4 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 12 +++--- examples/SendRawDemo/SendRawDemo.ino | 4 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 12 +++--- examples/SimpleReceiver/SimpleReceiver.ino | 5 ++- .../PinDefinitionsAndMore.h | 12 +++--- examples/SimpleSender/PinDefinitionsAndMore.h | 12 +++--- examples/SimpleSender/SimpleSender.ino | 4 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 12 +++--- examples/TinySender/PinDefinitionsAndMore.h | 12 +++--- examples/UnitTest/PinDefinitionsAndMore.h | 12 +++--- pictures/IRReceiverPinout.jpg | Bin 0 -> 36852 bytes src/IRReceive.hpp | 35 +++++++++++++----- src/IRremote.hpp | 2 + src/private/IRTimer.hpp | 2 + 37 files changed, 231 insertions(+), 137 deletions(-) create mode 100644 pictures/IRReceiverPinout.jpg diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 734432f14..ab146aa92 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -69,6 +69,7 @@ jobs: # - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 - esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80 - esp32:esp32:featheresp32:FlashFreq=80 + - esp32:esp32:esp32c3 - STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 - STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072 - stm32duino:STM32F1:genericSTM32F103C @@ -242,6 +243,13 @@ jobs: IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 + - arduino-boards-fqbn: esp32:esp32:esp32c3 + platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + sketches-exclude: TinyReceiver # undefined reference to `TwoWire::onReceive(void (*)(int))' + build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized + All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 + # # STM # diff --git a/README.md b/README.md index 3f80d4042..493262dfb 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,7 @@ Protocols can be switched off and on by defining macros before the line `#includ - Allows receiving and sending of **raw timing data**. ## New features with version 4.x +- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead. - New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols. - Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`. - RawData type is now 64 bit for 32 bit platforms and therefore `decodedIRData.decodedRawData` can contain complete frame information for more protocols than with 32 bit as before. @@ -120,7 +121,7 @@ Protocols can be switched off and on by defining macros before the line `#includ - The parameter `bool hasStopBit` is not longer required and removed e.g. for function `sendPulseDistanceWidth()`. ## New features with version 3.x -- **Any pin** can be used for sending -if `SEND_PWM_BY_TIMER` is not defined- and receiving. +- **Any pin** can be used for receiving and if `SEND_PWM_BY_TIMER` is not defined also for sending. - Feedback LED can be activated for sending / receiving. - An 8/16 bit ****command** value as well as an 16 bit **address** and a protocol number is provided for decoding (instead of the old 32 bit value). - Protocol values comply to **protocol standards**.
@@ -147,7 +148,7 @@ If you use an (old) Arduino core that does not use the `-flto` flag for compile, - Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar. - Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106) or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin();` or `IrSender.begin(DISABLE_LED_FEEDBACK);` 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);` - 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 @@ -292,6 +293,8 @@ The following macros will definitely be overridden with default values otherwise
# Receiving IR codes +![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) + Check for a **completly received IR frame** with:
`if (IrReceiver.decode()) {}`
This also decodes the received data.
@@ -711,7 +714,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | | `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | -| `DISABLE_CODE_FOR_RECEIVER` | disabled | Saves up to 450 bytes program memory and 269 bytes RAM if receiving functionality is not required. | +| `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. | diff --git a/changelog.md b/changelog.md index 089c9c12a..aa8db26e8 100644 --- a/changelog.md +++ b/changelog.md @@ -3,13 +3,14 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.3.0 +- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). + Therefore IrSender.begin(DISABLE_LED_FEEDBACK) will not longer work! - Added convenience function isIRReceiverAttachedForTinyReceiver(). - Added Extended NEC Protocol macro to TinyIR by Buzzerb. - Fixed sendSamsung() / sendSamsungLG() bug. - Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). - Added rawlen and initialGap to IRData. - Added ReceiveAndSendHobToHood example. -- Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 7cf97edca..54257fa85 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -33,7 +33,9 @@ */ #include -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #include diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 1a23cd4cf..bbcc94960 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -34,8 +34,9 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. - +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif //#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition @@ -343,6 +344,9 @@ void loop() { IRSendData.command = sCommand; IRSendData.flags = IRDATA_FLAGS_EMPTY; + Serial.println(F("Send next protocols with IrSender.write")); + Serial.flush(); + IRSendData.protocol = SAMSUNG; Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index 3b8ac4690..5b73aee40 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -42,7 +42,9 @@ //#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol #define NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU 5 -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif #define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver. //#define DEBUG // Activate this for more output from the LG-AC driver. diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index 6096a9b70..5f6ff2e30 100644 --- a/examples/SendProntoDemo/SendProntoDemo.ino +++ b/examples/SendProntoDemo/SendProntoDemo.ino @@ -32,7 +32,9 @@ */ #include -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #include diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 77ea3cc8a..e19ed9a3c 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -37,7 +37,9 @@ */ #include -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 87ec5c1b8..b36e46a39 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -1,7 +1,8 @@ /* * SimpleReceiver.cpp * - * Demonstrates receiving NEC IR codes with IRremote + * Demonstrates receiving ONLY NEC protocol IR codes with IRremote + * If no protocol is defined, all protocols (except Bang&Olufsen) are active. * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * @@ -40,7 +41,7 @@ //#define DECODE_KASEIKYO //#define DECODE_PANASONIC // alias for DECODE_KASEIKYO //#define DECODE_LG -#define DECODE_NEC // Includes Apple and Onkyo +#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line. //#define DECODE_SAMSUNG //#define DECODE_SONY //#define DECODE_RC5 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index a1e2515d3..bf226cb07 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -13,7 +13,9 @@ */ #include -#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used. +#if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. +#define DISABLE_CODE_FOR_RECEIVER // Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. +#endif //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 54395f68e..1ed4dd45d 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -42,6 +42,7 @@ * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 + * ESP32-C3 6 7 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -173,11 +174,12 @@ #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#define IR_RECEIVE_PIN 8 -#define IR_SEND_PIN 9 -#define TONE_PIN 10 // ADC2_0 -#define APPLICATION_PIN 11 +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 #elif defined(ESP32) #include diff --git a/pictures/IRReceiverPinout.jpg b/pictures/IRReceiverPinout.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5e232d15731db63c6d73252357c2393b135316fe GIT binary patch literal 36852 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 literal 0 HcmV?d00001 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 452604db4..2d0507a01 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -309,11 +309,30 @@ void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8 void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) { irparams.IRReceivePin = aReceivePinNumber; #if defined(__AVR__) - irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); - irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); +# if defined(__digitalPinToBit) + if (__builtin_constant_p(aReceivePinNumber)) { + irparams.IRReceivePinMask = 1UL << (__digitalPinToBit(aReceivePinNumber)); + } else { + irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?) + } +# else + irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?) +# endif +# if defined(__digitalPinToPINReg) + /* + * This code is 54 bytes smaller, if aReceivePinNumber is a constant :-), but 38 byte longer if it is not constant (,which is not likely). + */ + if (__builtin_constant_p(aReceivePinNumber)) { + irparams.IRReceivePinPortInputRegister = __digitalPinToPINReg(aReceivePinNumber); + } else { + irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced + } +# else + irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced +# endif #endif - // Set pin mode once. pinModeFast makes no difference here :-( - pinMode(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32 + // Set pin mode once. pinModeFast makes no difference if used, but saves 224 if not referenced :-( + pinModeFast(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32 } /** @@ -903,10 +922,12 @@ uint_fast8_t IRrecv::getBiphaselevel() { return tLevelOfCurrentInterval; } -#if defined(DECODE_HASH) /********************************************************************************************************************** * Internal Hash decode function **********************************************************************************************************************/ +#define FNV_PRIME_32 16777619 ///< used for decodeHash() +#define FNV_BASIS_32 2166136261 ///< used for decodeHash() + /** * Compare two (tick) values for Hash decoder * Use a tolerance of 20% to enable e.g. 500 and 600 (NEC timing) to be equal @@ -922,9 +943,6 @@ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) { return 1; } -#define FNV_PRIME_32 16777619 ///< used for decodeHash() -#define FNV_BASIS_32 2166136261 ///< used for decodeHash() - /** * decodeHash - decode an arbitrary IR code. * Instead of decoding using a standard encoding scheme @@ -989,7 +1007,6 @@ bool IRrecv::decodeHashOld(decode_results *aResults) { return true; } -#endif // DECODE_HASH /********************************************************************************************************************** * Match functions diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 6f8bcf526..af85e04c9 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -271,6 +271,8 @@ #warning INFO: No definition for LED_BUILTIN found -> default LED feedback is disabled. # endif #include "IRFeedbackLED.hpp" +# else +void disableLEDFeedback() {}; // dummy function for examples # endif #include "LongUnion.h" // used in most decoders diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index d7acb48fe..a7243dead 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1469,6 +1469,7 @@ void timerDisableReceiveInterrupt() { #undef ISR # endif +# if !defined(DISABLE_CODE_FOR_RECEIVER) // &IRReceiveTimerInterruptHandler is referenced, but not available void timerConfigForReceive() { // ESP32 has a proper API to setup timers, no weird chip macros needed // simply call the readable API versions :) @@ -1480,6 +1481,7 @@ void timerConfigForReceive() { } // every 50 us, autoreload = true } +# endif # if !defined(IR_SEND_PIN) uint8_t sLastSendPin = 0; // To detach before attach, if already attached From 672d5cb5327b25d2290c650cfe786717ca05a119 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 8 Mar 2024 09:21:13 +0100 Subject: [PATCH 034/133] Changed RECORD_GAP_MICROS default value from 5000 to 8000 --- README.md | 4 +++- changelog.md | 1 + examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 +- .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 2 +- examples/ReceiveDump/ReceiveDump.ino | 2 +- examples/SendAndReceive/SendAndReceive.ino | 2 +- src/IRremote.hpp | 2 +- src/ir_DistanceWidthProtocol.hpp | 2 +- 10 files changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 493262dfb..16b7eb645 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [Staying on 2.x](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#staying-on-2x) - [Why *.hpp instead of *.cpp](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp) - [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files) +- [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts) - [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes) * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure) * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols) @@ -292,9 +293,10 @@ The following macros will definitely be overridden with default values otherwise
-# Receiving IR codes +# IRReceiver pinouts ![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) +# Receiving IR codes Check for a **completly received IR frame** with:
`if (IrReceiver.decode()) {}`
This also decodes the received data.
diff --git a/changelog.md b/changelog.md index aa8db26e8..74d08b45f 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Added functions stopTimer(), restartTimer() and restartTimerWithTicksToAdd(). - Added rawlen and initialGap to IRData. - Added ReceiveAndSendHobToHood example. +- Changed RECORD_GAP_MICROS default value from 5000 to 8000. # 4.2.1 - Fix wrong type of tEnableLEDFeedback in IRSend.hpp and IRReceive.hpp. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 808ab666d..d363df589 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -59,7 +59,7 @@ // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. #define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules. -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols. +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols. //#define DEBUG // Activate this for lots of lovely debug output from the decoders. //#define DECODE_NEC // Includes Apple and Onkyo diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index f763be284..10f7fe86d 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -82,7 +82,7 @@ //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active //#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index c9ded9475..1f9813583 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -66,7 +66,7 @@ #endif //#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 222e9ce47..554c128bc 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -92,7 +92,7 @@ // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. //#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity. -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define DEBUG // Activate this for lots of lovely debug output from the decoders. diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 93efcfca4..22d5a6f55 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -56,7 +56,7 @@ */ #define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 20 is recommended for the cheap VS1838 modules. -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define DEBUG // Activate this for lots of lovely debug output from the decoders. #include diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 8eb75ab3b..669de50c5 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -39,7 +39,7 @@ //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active //#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory -//#define RECORD_GAP_MICROS 12000 // Default is 5000. Activate it for some LG air conditioner protocols +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition diff --git a/src/IRremote.hpp b/src/IRremote.hpp index af85e04c9..a7af9fdc2 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -158,7 +158,7 @@ */ #if !defined(RECORD_GAP_MICROS) // To change this value, you simply can add a line #define "RECORD_GAP_MICROS " in your ino file before the line "#include " -#define RECORD_GAP_MICROS 5000 // FREDRICH28AC / LG2 header space is 9700, NEC header space is 4500 +#define RECORD_GAP_MICROS 8000 // RECS80 (https://www.mikrocontroller.net/articles/IRMP#RECS80) 1 bit space is 7500µs , NEC header space is 4500 #endif /** * Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value. diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index e5c0b4712..22d9ad8fb 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -231,7 +231,7 @@ bool IRrecv::decodeDistanceWidth() { Serial.print(F("PULSE_DISTANCE_WIDTH: ")); Serial.print(F("Space ")); Serial.print(tDurationTicks * MICROS_PER_TICK); - Serial.print(F(" is longer than ")); + Serial.print(F(" is longer than maximum ")); Serial.print(DURATION_ARRAY_SIZE * MICROS_PER_TICK); Serial.print(F(" us. Index=")); Serial.println(i); From c6c7f17f587eabab0833fe0d048dba85251a9735 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 10 Mar 2024 02:11:32 +0100 Subject: [PATCH 035/133] Documentation --- README.md | 5 ++++- examples/ReceiveDump/ReceiveDump.ino | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 16b7eb645..58c51e1e2 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ The following macros will definitely be overridden with default values otherwise ![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) # Receiving IR codes -Check for a **completly received IR frame** with:
+In your program you check for a **completly received IR frame** with:
`if (IrReceiver.decode()) {}`
This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`. @@ -381,6 +381,9 @@ But be careful, the NEC2 protocol can only be detected by the NEC library decode 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).
diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 22d5a6f55..b716ba104 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -126,8 +126,6 @@ void loop() { IrReceiver.compensateAndPrintIRResultAsCArray(&Serial, true); // Output the results as uint16_t source code array of micros IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables Serial.println(); // blank line between entries - IrReceiver.printIRSendUsage(&Serial); - Serial.println(); // blank line between entries IrReceiver.compensateAndPrintIRResultAsPronto(&Serial); From 02c0e24da9f75b03af53410ccfc02cf3380f23a8 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 15 Mar 2024 20:54:05 +0100 Subject: [PATCH 036/133] Documentation --- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 6 +++--- examples/ControlRelay/PinDefinitionsAndMore.h | 6 +++--- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- examples/MicroGirs/PinDefinitionsAndMore.h | 6 +++--- examples/ReceiveAndSend/PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- examples/ReceiveDemo/PinDefinitionsAndMore.h | 6 +++--- examples/ReceiveDemo/ReceiveDemo.ino | 16 ++++++++++------ examples/ReceiveDump/PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- examples/SendAndReceive/PinDefinitionsAndMore.h | 6 +++--- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 6 +++--- examples/SendDemo/PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- examples/SendProntoDemo/PinDefinitionsAndMore.h | 6 +++--- examples/SendRawDemo/PinDefinitionsAndMore.h | 6 +++--- examples/SimpleReceiver/PinDefinitionsAndMore.h | 6 +++--- .../PinDefinitionsAndMore.h | 6 +++--- examples/SimpleSender/PinDefinitionsAndMore.h | 6 +++--- examples/TinyReceiver/PinDefinitionsAndMore.h | 6 +++--- examples/TinyReceiver/TinyReceiver.ino | 15 +++++++++++---- examples/TinySender/PinDefinitionsAndMore.h | 6 +++--- examples/UnitTest/PinDefinitionsAndMore.h | 6 +++--- examples/UnitTest/UnitTest.ino | 2 +- src/IRProtocol.h | 2 +- src/IRReceive.hpp | 2 +- src/TinyIRReceiver.hpp | 3 +++ 29 files changed, 96 insertions(+), 82 deletions(-) diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 554c128bc..002c21812 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -137,13 +137,16 @@ void setup() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. Serial.println(); - Serial.print(F("If you connect debug pin ")); + if (digitalRead(DEBUG_BUTTON_PIN) != LOW) { + Serial.print(F("If you connect debug pin ")); # if defined(APPLICATION_PIN_STRING) - Serial.print(APPLICATION_PIN_STRING); + Serial.print(APPLICATION_PIN_STRING); # else - Serial.print(DEBUG_BUTTON_PIN); + Serial.print(DEBUG_BUTTON_PIN); # endif - Serial.println(F(" to ground, raw data is always printed")); + Serial.print(F(" to ground, ")); + } + Serial.println(F("raw data is always printed")); // infos for receive Serial.print(RECORD_GAP_MICROS); @@ -201,9 +204,10 @@ void loop() { Serial.println(F("Received noise or an unknown (or not yet enabled) protocol")); } IrReceiver.printIRResultRawFormatted(&Serial, true); - } else { + } + if (IrReceiver.decodedIRData.protocol != UNKNOWN) { /* - * This is the info output for a successful receive in normal mode + * The info output for a successful receive */ IrReceiver.printIRResultShort(&Serial); IrReceiver.printIRSendUsage(&Serial); diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index cafbe9df4..ce6067cba 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -26,7 +26,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -56,13 +56,17 @@ //#define TRACE // to see the state of the ISR state machine /* - * Set compile options to modify the generated code. + * Protocol selection */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. -//#define USE_FAST_PROTOCOL // Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC / ONKYO. -//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. +//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. +/* + * Set compile options to modify the generated code. + */ +//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the fixed function "void handleReceivedTinyIRData()" each time a frame or repeat is received. #include "TinyIRReceiver.hpp" // include the code @@ -113,6 +117,9 @@ 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(); } diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 1ed4dd45d..d53c88aae 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -41,9 +41,9 @@ * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * SAMD21 3 4 5 * ESP8266 14|D5 12|D6 % - * ESP32 15 4 27 - * ESP32-C3 6 7 - * BluePill PA6 PA7 PA3 + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 0a254165a..bc75f6fb3 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2023 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/IRProtocol.h b/src/IRProtocol.h index c4368364b..0404258ea 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -118,7 +118,7 @@ struct IRData { uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above - //These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0. + // These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0. #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR uint_fast8_t rawlen; ///< counter of entries in rawbuf #else diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 2d0507a01..d793680be 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1473,7 +1473,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { */ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) { - uint8_t tRawlen = decodedIRData.rawlen; // Get it once here in order to print quite consistent data, even if ISR is running + uint8_t tRawlen = decodedIRData.rawlen; // Print Raw data aSerial->print(F("rawData[")); aSerial->print(tRawlen, DEC); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 9f7874358..19c47bc4a 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -76,6 +76,9 @@ //#define LOCAL_DEBUG // This enables debug output only for this file #endif +/* + * Protocol selection + */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. From 59f4ce4a7f94ac016048abbcbe505c9b2343d1af Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 15 Mar 2024 22:35:35 +0100 Subject: [PATCH 037/133] Fixed bug #1214 8 bit overflow for variable containing rawlen. --- src/IRReceive.hpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index d793680be..904cff384 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -853,9 +853,9 @@ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a /* * Static variables for the getBiphaselevel function */ -uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array -uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. -uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. +uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array +uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. +uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. uint16_t sBiphaseTimeUnit; void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) { @@ -1281,7 +1281,12 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf uint32_t IRrecv::getTotalDurationOfRawData() { uint16_t tSumOfDurationTicks = 0; - for (uint_fast8_t i = 1; i < decodedIRData.rawlen; i++) { +#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR + uint_fast8_t i; +#else + unsigned int i; +#endif + for (i = 1; i < decodedIRData.rawlen; i++) { tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i]; } return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK; @@ -1473,10 +1478,9 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { */ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) { - uint8_t tRawlen = decodedIRData.rawlen; // Print Raw data aSerial->print(F("rawData[")); - aSerial->print(tRawlen, DEC); + aSerial->print(decodedIRData.rawlen, DEC); aSerial->println(F("]: ")); /* @@ -1513,7 +1517,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI uint32_t tDuration; uint16_t tSumOfDurationTicks = 0; - for (i = 1; i < tRawlen; i++) { + for (i = 1; i < decodedIRData.rawlen; i++) { auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (aOutputMicrosecondsInsteadOfTicks) { tDuration = tCurrentTicks * MICROS_PER_TICK; @@ -1540,7 +1544,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI } aSerial->print(tDuration, DEC); - if ((i & 1) && (i + 1) < tRawlen) { + if ((i & 1) && (i + 1) < decodedIRData.rawlen) { aSerial->print(','); //',' not required for last one } From b962db8f4e47408df01474a57f313f5a6bbe39a1 Mon Sep 17 00:00:00 2001 From: Armin Date: Sat, 16 Mar 2024 01:15:06 +0100 Subject: [PATCH 038/133] Bumped version to 4.3.1. Fixed overflow bug for rawlen > 254. Removed deprecated sendPulseDistance... functions with parameter aSendStopBit. --- changelog.md | 4 ++ .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 3 +- library.json | 2 +- library.properties | 2 +- src/IRProtocol.h | 11 +--- src/IRReceive.hpp | 39 +++---------- src/IRSend.hpp | 58 ++++++------------- src/IRVersion.h | 4 +- src/IRremoteInt.h | 25 +++----- src/ir_DistanceWidthProtocol.hpp | 20 ++++--- 10 files changed, 58 insertions(+), 110 deletions(-) diff --git a/changelog.md b/changelog.md index 74d08b45f..cebf37121 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.3.1 + - Fixed overflow bug for rawlen > 254. + - Removed deprecated sendPulseDistance... functions with parameter aSendStopBit. + # 4.3.0 - Removed default value USE_DEFAULT_FEEDBACK_LED_PIN for last parameter of IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). Therefore IrSender.begin(DISABLE_LED_FEEDBACK) will not longer work! diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index d363df589..ecdd71148 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -241,7 +241,8 @@ void loop() { ) { // Print more info, but only if we are connected to USB, i.e. VCC is > 4300 mV, because this may take to long to detect some fast repeats IrReceiver.printIRSendUsage(&Serial); - IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-) +// IrReceiver.printIRResultRawFormatted(&Serial, false); // print ticks, this is faster :-) + IrReceiver.printIRResultRawFormatted(&Serial); // print us, this is better to compare :-) } // Guarantee at least 5 millis for tone. decode starts 5 millis (RECORD_GAP_MICROS) after end of frame diff --git a/library.json b/library.json index 0bf219620..2d6f03451 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/z3t0/Arduino-IRremote.git" }, - "version": "4.3.0", + "version": "4.3.1", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index cc6e5e957..69d5084fd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.3.0 +version=4.3.1 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 0404258ea..95f59b039 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -119,11 +119,7 @@ struct IRData { uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above // These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0. -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t rawlen; ///< counter of entries in rawbuf -#else - uint_fast16_t rawlen; ///< counter of entries in rawbuf -#endif + IRRawlenType rawlen; ///< counter of entries in rawbuf uint16_t initialGap; ///< rawbuf[0] contains the initial gap of the last frame. irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by receiving ISR. @@ -141,12 +137,9 @@ struct PulseDistanceWidthProtocolConstants { /* * Definitions for member PulseDistanceWidthProtocolConstants.Flags */ -#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20 +#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20 // Stop bit is otherwise sent for all pulse distance protocols. #define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST #define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST -// 2 definitions for deprecated parameter bool aSendStopBit -#define SEND_STOP_BIT true -#define SEND_NO_STOP_BIT false /* * Carrier frequencies for various protocols diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 904cff384..f174717b4 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -700,7 +700,7 @@ bool IRrecv::decode() { * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first. * @return true If decoding was successful */ -bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros, +bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) { auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset]; @@ -843,7 +843,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8 * @return true if decoding was successful */ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, - uint_fast8_t aStartOffset) { + IRRawlenType aStartOffset) { return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, @@ -967,12 +967,7 @@ bool IRrecv::decodeHash() { if (decodedIRData.rawlen < 6) { return false; } -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t i; -#else - unsigned int i; -#endif - for (i = 1; (i + 2) < decodedIRData.rawlen; i++) { + for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) { // Compare mark with mark and space with space uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]); // Add value into the hash @@ -1281,12 +1276,8 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf uint32_t IRrecv::getTotalDurationOfRawData() { uint16_t tSumOfDurationTicks = 0; -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t i; -#else - unsigned int i; -#endif - for (i = 1; i < decodedIRData.rawlen; i++) { + + for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i]; } return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK; @@ -1492,11 +1483,6 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI } else { aSerial->println(decodedIRData.initialGap, DEC); } -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t i; -#else - unsigned int i; -#endif // Newline is printed every 8. value, if tCounterForNewline % 8 == 0 uint_fast8_t tCounterForNewline = 6; // first newline is after the 2 values of the start bit @@ -1517,7 +1503,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI uint32_t tDuration; uint16_t tSumOfDurationTicks = 0; - for (i = 1; i < decodedIRData.rawlen; i++) { + for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (aOutputMicrosecondsInsteadOfTicks) { tDuration = tCurrentTicks * MICROS_PER_TICK; @@ -1586,12 +1572,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr aSerial->print(F("] = {")); // Start declaration // Dump data -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t i; -#else - unsigned int i; -#endif - for (i = 1; i < decodedIRData.rawlen; i++) { + for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK; if (i & 1) { @@ -1638,11 +1619,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) { // Store data, skip leading space# -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t i; -#else - unsigned int i; -#endif + IRRawlenType i; for (i = 1; i < decodedIRData.rawlen; i++) { uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK; if (i & 1) { diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 00363a300..5fefca80c 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -521,21 +521,8 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf * For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on. * The output always ends with a space * Stop bit is always sent + * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. */ -void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, - uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, - IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, - uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { - uint8_t tFlags = 0; - if (aMSBFirst) { - tFlags = PROTOCOL_IS_MSB_FIRST; - } - (void) aSendStopBit; - - sendPulseDistanceWidthFromArray(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, - aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats); -} - void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { @@ -545,7 +532,6 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, Distanc aDistanceWidthTimingInfo->ZeroSpaceMicros, aDecodedRawDataArray, aNumberOfBits, aFlags, aRepeatPeriodMillis, aNumberOfRepeats); } - void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, @@ -616,6 +602,9 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_ * For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on. * The output always ends with a space * Stop bit is always sent + * @param aNumberOfBits Number of bits from aDecodedRawDataArray to be actually sent. + * @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified + * then it is called without leading and trailing space. */ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { @@ -692,7 +681,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants } /** - * Sends PulseDistance frames and repeats and enables receiver again + * Sends PulseDistance frames and repeats * @param aProtocolConstants The constants to use for sending this protocol. * @param aData uint32 or uint64 holding the bits to be sent. * @param aNumberOfBits Number of bits from aData to be actually sent. @@ -761,23 +750,11 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc * @param aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aFlags, aRepeatPeriodMillis Values to use for sending this protocol, also contained in the PulseDistanceWidthProtocolConstants of this protocol. * @param aData uint32 or uint64 holding the bits to be sent. * @param aNumberOfBits Number of bits from aData to be actually sent. + * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. * @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified * then it is called without leading and trailing space. * @param aSpecialSendRepeatFunction If NULL, the first frame is repeated completely, otherwise this function is used for sending the repeat frame. */ -void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, - uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData, - uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats, - void (*aSpecialSendRepeatFunction)()) { - uint8_t tFlags = 0; - if (aMSBFirst) { - tFlags = PROTOCOL_IS_MSB_FIRST; - } - (void) aSendStopBit; - sendPulseDistanceWidth(aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, - aZeroSpaceMicros, aData, aNumberOfBits, tFlags, aRepeatPeriodMillis, aNumberOfRepeats, aSpecialSendRepeatFunction); - -} void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats, @@ -825,9 +802,12 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader } /** - * Sends PulseDistance data + * Sends PulseDistance from data contained in parameter using ProtocolConstants structure for timing etc. * The output always ends with a space * Each additional call costs 16 bytes program memory + * @param aProtocolConstants The constants to use for sending this protocol. + * @param aData uint32 or uint64 holding the bits to be sent. + * @param aNumberOfBits Number of bits from aData to be actually sent. */ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, uint_fast8_t aNumberOfBits) { @@ -838,18 +818,13 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr } /** - * Sends PulseDistance data + * Sends PulseDistance data with timing parameters and flag parameters. * The output always ends with a space + * @param aOneMarkMicros Timing for sending this protocol. + * @param aData uint32 or uint64 holding the bits to be sent. + * @param aNumberOfBits Number of bits from aData to be actually sent. + * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. */ -void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, - uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit) { - uint8_t tFlags = 0; - if (aMSBFirst) { - tFlags = PROTOCOL_IS_MSB_FIRST; - } - (void) aSendStopBit; - sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aData, aNumberOfBits, tFlags); -} void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) { @@ -885,6 +860,7 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp /* * Stop bit is sent for all pulse distance protocols i.e. aOneMarkMicros == aZeroMarkMicros. * Therefore it is not sent for Sony and Magiquest :-) + * For sending from an array, no intermediate stop bit must be sent for first data chunk. */ if (!(aFlags & SUPPRESS_STOP_BIT_FOR_THIS_DATA) && aOneMarkMicros == aZeroMarkMicros) { // Send stop bit here @@ -905,6 +881,8 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp * 1 -> space+mark * The output always ends with a space * can only send 31 bit data, since we put the start bit as 32th bit on front + * @param aData uint32 or uint64 holding the bits to be sent. + * @param aNumberOfBits Number of bits from aData to be actually sent. */ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits) { diff --git a/src/IRVersion.h b/src/IRVersion.h index 486d10778..5d5bfde39 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.3.0" +#define VERSION_IRREMOTE "4.3.1" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 3 -#define VERSION_IRREMOTE_PATCH 0 +#define VERSION_IRREMOTE_PATCH 1 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index c39fca9fc..452231961 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -79,6 +79,11 @@ #error RAW_BUFFER_LENGTH must be even, since the array consists of space / mark pairs. #endif +#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR +typedef uint_fast8_t IRRawlenType; +#else +typedef unsigned int IRRawlenType; +#endif /**************************************************** * Declarations for the receiver Interrupt Service Routine ****************************************************/ @@ -105,11 +110,7 @@ struct irparams_struct { void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP #endif bool OverflowFlag; ///< Raw buffer OverflowFlag occurred -#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR - uint_fast8_t rawlen; ///< counter of entries in rawbuf -#else - uint_fast16_t rawlen; ///< counter of entries in rawbuf -#endif + IRRawlenType rawlen; ///< counter of entries in rawbuf uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command }; @@ -249,12 +250,12 @@ class IRrecv { * The main decoding functions used by the individual decoders */ bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, - uint_fast8_t aStartOffset = 3); + IRRawlenType aStartOffset = 3); - bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros, + bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst); - bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount, + bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint_fast8_t aStartClockCount, uint_fast8_t aValueOfSpaceToMarkTransition, uint16_t aBiphaseTimeUnit); void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit); @@ -458,11 +459,6 @@ class IRsend { uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats); - void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, - uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, - IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, - uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) - __attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required."))); void sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); void sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo, @@ -484,9 +480,6 @@ class IRsend { __attribute__ ((deprecated ("Since version 4.1.0 parameter aSendStopBit is not longer required."))); void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags); - void sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, - uint16_t aZeroSpaceMicros, IRRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit) - __attribute__ ((deprecated ("Since version 4.1.0 last parameter aSendStopBit is not longer required."))); void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits); void mark(uint16_t aMarkMicros); diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 22d9ad8fb..258de8246 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -23,8 +23,8 @@ * https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L175 * sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros, * unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros, - * unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, bool aMSBFirst, - * bool aSendStopBit, unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) + * unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, uint8_t aFlags, + * unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * @@ -163,8 +163,6 @@ bool IRrecv::decodeDistanceWidth() { return false; } - uint_fast8_t i; - // Reset duration array memset(tDurationArray, 0, DURATION_ARRAY_SIZE); @@ -172,7 +170,7 @@ bool IRrecv::decodeDistanceWidth() { /* * Count number of mark durations up to 49 ticks. Skip leading start and trailing stop bit. */ - for (i = 3; i < (uint_fast8_t) decodedIRData.rawlen - 2; i += 2) { + for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) { auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (tDurationTicks < DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; // count duration if less than DURATION_ARRAY_SIZE (50) @@ -219,7 +217,7 @@ bool IRrecv::decodeDistanceWidth() { * Count number of space durations. Skip leading start and trailing stop bit. */ tIndexOfMaxDuration = 0; - for (i = 4; i < (uint_fast8_t) decodedIRData.rawlen - 2; i += 2) { + for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) { auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i]; if (tDurationTicks < DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; @@ -284,9 +282,12 @@ bool IRrecv::decodeDistanceWidth() { Serial.print(F(", ")); Serial.println(tSpaceTicksShort * MICROS_PER_TICK); #endif - uint8_t tStartIndex = 3; - // skip leading start bit for decoding. - uint16_t tNumberOfBits = (decodedIRData.rawlen / 2) - 1; +#if RAW_BUFFER_LENGTH <= 508 + uint_fast8_t tNumberOfBits; +#else + uint16_t tNumberOfBits; +#endif + tNumberOfBits = (decodedIRData.rawlen / 2) - 1; if (tSpaceTicksLong > 0 && tMarkTicksLong == 0) { // For PULSE_DISTANCE a stop bit is mandatory, for PULSE_WIDTH it is not required! tNumberOfBits--; // Correct for stop bit @@ -320,6 +321,7 @@ bool IRrecv::decodeDistanceWidth() { unsigned int tMarkMicrosShort = tMarkTicksShort * MICROS_PER_TICK; unsigned int tMarkMicrosLong = tMarkTicksLong * MICROS_PER_TICK; unsigned int tSpaceMicrosLong = tSpaceTicksLong * MICROS_PER_TICK; + IRRawlenType tStartIndex = 3; // skip leading start bit for decoding. for (uint_fast8_t i = 0; i <= tNumberOfAdditionalArrayValues; ++i) { uint8_t tNumberOfBitsForOneDecode = tNumberOfBits; From d781c176200e7b1946b630acd1251eda76f3a6c1 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 7 Apr 2024 20:20:49 +0200 Subject: [PATCH 039/133] Documentation --- README.md | 31 +++++++++------- .../AllProtocolsOnLCD/LiquidCrystal_I2C.cpp | 33 ++++++++++++++++-- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 4 +++ library.json | 2 +- pictures/BoseWaveSoundTouch_IV.jpg | Bin 0 -> 152295 bytes src/IRReceive.hpp | 6 ++-- src/ir_BoseWave.hpp | 6 ++-- src/ir_Lego.hpp | 1 + src/private/IRTimer.hpp | 17 +++++---- 9 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 pictures/BoseWaveSoundTouch_IV.jpg diff --git a/README.md b/README.md index 58c51e1e2..db3f67a1c 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) - [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) + * [Receiving does not run if analogWrite() or tone() is used.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-does-not-run-if-analogwrite-or-tone-is-used) * [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) @@ -242,16 +243,14 @@ Most likely your code will run and you will not miss the new features. Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
It may be sufficient and deals flawlessly with 32 bit IR codes.
-If this doesn't fit your case, be assured that 3.x is at least trying to be backwards compatible, so your old examples should still work fine. +If this doesn't fit your case, be assured that 4.x is at least trying to be backwards compatible, so your old examples should still work fine. -### Drawbacks +### Drawbacks of using 2.x - Only the following decoders are available:
` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` - The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. -- The old functions `sendNEC()` and `sendJVC()` are renamed to `sendNECMSB()` and `sendJVCMSB()`.
- Use them to send your **old MSB-first 32 bit IR data codes**. -- No decoding by a (constant) 8/16 bit address and an 8 bit command. +- No decoding to a more meaningfull (constant) 8/16 bit address and 8 bit command.
@@ -411,7 +410,8 @@ If you handle the sending of repeat frames by your own, you must insert sensible The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)` are kept for backward compatibility to **(old)** tutorials and unsupported as well as error prone. ## Send pin -Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active. +Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
+On **ESP32** ledc channel 0 is used for gereating 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). ### List of public IR code databases @@ -508,6 +508,10 @@ void loop() {} The FAST protocol can be received by IRremote and TinyIRReceiver. # FAQ and hints +## Receiving does not run if analogWrite() or tone() is used. +The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). On some boards where a software timer is available, the software timer is used.
+Be aware that the hardware timer used for receiving should not be used for analogWrite().
+On the Uno and other AVR boards the receiver timer ist the same as the tone timer, so 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. ## 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).
@@ -695,7 +699,7 @@ Here you see the delay of the receiver output (blue) from the IR diode input (ye # Issues and discussions - Do not open an issue without first testing some of the examples! - If you have a problem, please post the MCVE (Minimal Complete Verifiable Example) showing this problem. My experience is, that most of the times you will find the problem while creating this MCVE :smile:. -- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us help you when we can read your code!** +- [Use code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code); **it helps us to help you when we can read your code!**
@@ -764,6 +768,7 @@ 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)

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). @@ -786,7 +791,7 @@ ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/A - BluePill with STM32 - RP2040 based boards (Raspberry Pi Pico, Nano RP2040 Connect etc.) -For ESP8266/ESP32, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md) + We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side.
If you can provide **examples of using a periodic timer for interrupts** for the new board, and the board name for selection in the Arduino IDE, then you have way better chances to get your board supported by IRremote. @@ -794,7 +799,8 @@ 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. +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 **ESP32** `hw_timer_t` is used for receive interrupts and `ledc` channel 0 is used for gneating the IR PWM. 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! @@ -823,9 +829,10 @@ The code for the timer and the **timer selection** is located in [private/IRTime | ATmega168, **ATmega328** | 1, **2** | 9, **3** | 9 & 10, **3 & 11** | | ATmega1280, **ATmega2560** | 1, **2**, 3, 4, 5 | 5, 6, **9**, 11, 46 | 5, 6, **9**, 11, 46 | | ATmega4809 | **TCB0** | **A4** | | -| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 | +| Leonardo (Atmega32u4) | 1, 3, **4_HS** | 5, **9**, 13 | 5, **9**, 13 | | Zero (SAMD) | **TC3** | \*, **9** | | -| [ESP32](http://esp32.net/) | **Ledc chan. 0** | All pins | | +| [ESP8266](http://esp8266.net/) | **timer1** | % | | +| [ESP32](http://esp32.net/) | **hw_timer_t**
**Ledc channel 0** | All pins | | | [Sparkfun Pro Micro](https://www.sparkfun.com/products/12640) | 1, **3** | **5**, 9 | | | [Teensy 1.0](https://www.pjrc.com/teensy/pinout.html) | **1** | **17** | 15, 18 | | [Teensy 2.0](https://www.pjrc.com/teensy/pinout.html) | 1, 3, **4_HS** | 9, **10**, 14 | 12 | @@ -963,4 +970,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
-Copyright (c) 2020-2023 [Armin Joachimsmeyer](https://github.com/ArminJo) +Copyright (c) 2020-2024 [Armin Joachimsmeyer](https://github.com/ArminJo) diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp index 2659ef41f..3369306d2 100644 --- a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp +++ b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp @@ -1,4 +1,12 @@ // Based on the work by DFRobot +/* + * Extensions made by AJ 2023 + * Removed Arduino 0.x support + * Added SoftI2CMaste support, which drastically reduces program size. + * Added OLED stuff + * Added createChar() with PROGMEM input + * Added fast timing + */ #include "Arduino.h" @@ -23,6 +31,18 @@ inline size_t LiquidCrystal_I2C::write(uint8_t value) { #include "SoftWire.h" #endif +#if defined(__AVR__) +/* + * The datasheet says: a command need > 37us to settle. Enable pulse must be > 450ns. + * Use no delay for enable pulse after each command, + * because the overhead of this library seems to be using the 37 us and 450 ns. + * At least it works perfectly for all my LCD's connected to Uno, Nano etc. + * and it saves a lot of time in realtime applications using LCD as display, + * like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter + */ +#define USE_FAST_TIMING +#endif + // When the display powers up, it is configured as follows: // // 1. Display clear @@ -131,7 +151,11 @@ void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t line /********** high level commands, for the user! */ void LiquidCrystal_I2C::clear() { command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero +#if defined(USE_FAST_TIMING) delayMicroseconds(1500); // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK +#else + delayMicroseconds(2000); // this command takes a long time! +#endif if (_oled) setCursor(0, 0); } @@ -274,10 +298,13 @@ void LiquidCrystal_I2C::expanderWrite(uint8_t _data) { void LiquidCrystal_I2C::pulseEnable(uint8_t _data) { expanderWrite(_data | En); // En high -// delayMicroseconds(1); // enable pulse must be >450ns // AJ 20.9.23 not required for my LCD's - +#if !defined(USE_FAST_TIMING) + delayMicroseconds(1); // enable pulse must be > 450ns // AJ 20.9.23 not required for my LCD's +#endif expanderWrite(_data & ~En); // En low -// delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's +#if !defined(USE_FAST_TIMING) + delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's +#endif } // Alias functions diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 54257fa85..22d32b929 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -98,6 +98,10 @@ //#define BOSE_CMD_ALARM_ON_OFF 0x22 //#define BOSE_CMD_ALARM_WAKE_TO 0x70 //#define BOSE_CMD_ALARM_TIME 0x23 +// Different last 3 codes for Wave Sound Touch IV +//#define BOSE_CMD_ALARM_1 0x22 +//#define BOSE_CMD_ALARM_2 0x62 +//#define BOSE_CMD_ALARM_SETUP 0xA2 bool sPrintMenu; void printMenu(); diff --git a/library.json b/library.json index 2d6f03451..0e688c865 100644 --- a/library.json +++ b/library.json @@ -5,7 +5,7 @@ "repository": { "type": "git", - "url": "https://github.com/z3t0/Arduino-IRremote.git" + "url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git" }, "version": "4.3.1", "frameworks": "arduino", diff --git a/pictures/BoseWaveSoundTouch_IV.jpg b/pictures/BoseWaveSoundTouch_IV.jpg new file mode 100644 index 0000000000000000000000000000000000000000..17d535d9091e16590a3da0ef69c749cea31cb94c GIT binary patch literal 152295 zcmdqI1ymi+vNt-gad&rjcPDsocY?c1kl+LjP9Q+S27+sV1b5d!kl?{3xCOVj$v@|w zbI&{LzH{IGzV+7oiuBBHs;jE2yJxy<*GwK~A6Ed3=dud202CAeKtcY1$5nDX86P`q z08mh10uTTIK!Mc2JXHY{7!dde6F}JLP|&|6z>qo&2u6gQ3n7IF3ih}BCkQ6~gX(2>HpvxNE1LJJOBeZad2^QfD-@m-5Mef^9TDu zFjUfCGEh%_NJjeYT0Ddgo%~l@X%Gzh!v{a<{=tP14Esl>5`y8A|Lz0AAN=G3;y+-d zKk{`D`G{nAKpHY_Z4eCP{PB~Mg99q(?_&v_^Ve7oL&gjA2UCC`?f$_uknzR;`1f|9 z^5B2_|1`YN`G4^t5CHuHhW&%dA$+)h;8Wy71C&pC5Svf*WaH_25mGE6yMnIrj&xhpStIY&lTwrN=0U1p@8@Y2opk! z^G}{Y0aRhXZ+pni3=06#Z~#C81vEfzeYjw0S%eIuzw&lP+bcJaL_$IlG6ad zQq$w3jXf05JpcH3bpH6Lzy0voKm`rBX~X^>UCbc;`^WNM^;ex61pGV2%o^@rj@iGf z`y}_T{CKka@7i$t7e4&E`oG)%AL#$?|G&`xcYJ@6`Jd=N>HgOL7x(QG|NqH{|4RQ~ z&B_1iyx$AVzc|DfLIKc_HRk~3X>tBLRWd*UdyfEMk_Qb)CPD#^5InX1wC4QxC?B$B z9Yb^(A#2uu7ynl+$x6yff`HcmA7uZAxC)^s4rF@)pdhPYDG;L$Fbn|V@&My8@N))W zA%GHT0K_Grus#Fwwosr_Ku`+`zyu)rPe-=jM~EG)r}Y;K!ukIT{nhLL_uf`QNER~n zf7@y>|JrVT?}_kGO(;)8YYf?YG@b&f|5c<806r@JcVjRR7Ad6t{|Qk+l<^=X;-8Eh z{nM>W0jYnAn<)QD4zkt$9t#2pasQLfKZ*Wtxm1%<;^gDu=H%z4kdjoA=Hyn_l#}J) zRF$NV(vaem1$cNZ%&g7$%`B}2_&GVOEcm&sEiEni1+4_QxXrjNIU!LSWbU9LN64HB z3P8|5#9J7DkC~zW;HQ}RiQoXxpGf#=0{#{)7egYXzeUSc5d4qPG8FV*)*2vu=s#E+ z`?s77iW-0Uko=$jFE&nCMtonCO_8*mxxP z*f>PEn3x2V1Vp5y{NVh;xPd`HbMzC-C(h(IJuu`;805@<(fUt11KQK zlw*Q00dYX^fVvz%|L3Z7v;&*Abc})N?2q`v?LqjATU7Tqse2_ZFs<{~T0_1#zbZ|` z#U$A2cU4+N3i3B?2;y!v%|gAo+mh%H0fgmT4HXTpa`ovKjm^S{YexOL0=>aMKk}A+aoSMzuYhMlf1aFmzP}U*fWn z)OoozwR_0>y>iX3M4!feOZ1=$%cE->Kxfq$!njkyNnmm34N_FyLjD!D>vSzXE4%z% z)Xve3mRw!YD6Ext5Kqf&rv>QVtIXX$tH|A*Eqpz38$Ozd?w6O;$%JmBc`F|f*l*-- z(Zsh&bb*}Wd4IS(^`$5OttQi0SodTzY!Z5L=fHJHrH$=N8NBIDgf+#a!`WNeS!G!l z#;|o$=lZc1eau09PFPi18WSczOUrUkN^-Nv^ezq;bIv+f?$HC6{4j}gnoSS~?>!8& z*>ATd``5r@`Rwh5Y%;P)OgeAbmnq{_mghD=+m!|A2XeWi?NjeGNP|4xD@r69QZcDNo8hF6xqz@O@_Z>lS)TphWN#aW9ocJ zI|#-oe)6j;n5UJpcTiNuU}P8Iy2H_a-b`SzFsMMe8$p^QXH|0dJt(I7U}LgQpKY`g zVl68%lLv;&P2}CJORq8bfZ?&A#D^50@Jfq3c5-p4m5%OZcpJP#5XJVYz}dv^X0r{M zpLJfHr~lhur&=${%!=(@CyNUO^nHgyp$14i&ZnvirHXBKvu$`Kx^IJqI`x&4I+sk#g>etc zBM?~K6y9ROC4lcY#(uZ;{cAE8FgB)W^TJ*f<0#1OobW!+vsYD4d%}=uiEuYR>MKo> z%e&UwN0u#oLsV};2XVZ^W#28-BHw2qocK`4b$ zF{PrTT=i+~KCV>kP$-b)Yghl~T`p}cB_LDIG!LP?=im`wrTq|sGnmMPIw}tYsPF{t zP0S2y*Y53UWR*;)W8{qmE)X-I)2Q2l zL|LCv-*0S1YL47RgfHXdrkZ}1efzH2Q}b0p9g7SX%$2iYLr6WDg|>_P!zoUFz`hut zTwhny2J}C6^`EEqbGA$3EpS^EpjegIr zYLs>}eIfjSMFJ~qe+LfOEupQ}AOn0Lk&^~LLwdfdgdNrw_seT7blkJJxM9KkQ>eY* z3TAq0jBqZ(UUM~S82D~}JfzhMl}pPLsm_e> zS;ds2=qff}5Zg|N~7K!LN)=C{qcDeVbuQ@ilP?t zhm%nr$(zuP$%zqW6G27``P?Lq0$h*!>@*d$DnjZ@@3)wKIsN8hk_W{qTSdXao4xJd}cq z6nm#jr2cU3X;{3=;NX|Ms_UG0$)vDLB+nQH>XMpu>$r75?d4atSLJI~Pq-W|{yZ6g z%6yKmNi$q`;tyDy_u5=ll;#6r%`pDwAM-K&+T6ttVn&zevz&GerF9Q;3TuZwKi1J4 ze3|;5Or5ZICK`E8q_v~v2ir7z6A~=Z4}d-)tV=szu& zAn^mQONG!;{D>wL`c8;lBtJK+(u0l~v)<@bWP4*n^p(NOlrv<5=VX8VW5FI###+p} zf)oh_+m60cvLHN^CPh*|>t+EZF;NI8{aXan$U(RUnxI(bhr(mgX92>hlbRB1*T$|z ziG!~%eYB_O1X;nauF)y;unhf>_%vZ}ey+5k*#$E-SA*q5eC?iVAMcuwjt_qcv|Vto z|F$#psR_5qU`)ylpHeSX1L2tR_}HK0&T=zSV3ad=UCgv4+;Dsr2ymhR?aOvZ63z9hbjJ zI=PzjOZ@Ez2Bf?#ch$s6C)#3~g>N8f1!uPkTyi;R zs36=m0>`BtB|d3j2Cdkxx`KJLmC`;W;f1$n_|w?r<1T7LQDi`CWzdO1-ra`Kz{*Cd zxQX!3xGjGCy#)?|JB^|{soY-6qznsLr=04JQQ$Bzv)B%XSzu0)xuLrXc?%xg=7^cV z`drVRO2<1!Mw^0fgPM?#e8i(Pn)EDNRD-tQ4u+eSj5sdf+C?|=G#DZ@(34iVFb9YH7bIU zhEo4RHaz|tmkN9$h~}rMN+zGMLLYa>`FNS1P4SH{XZG~e#*OPdp}YaTjCq0H9nH&0 z*kq1--N~}phnhDce)f(lR=Ry5-svmxdw#wzj~w34!jG|ndFaNx%c>XeZoyVQ@F0<2+CJB9_0~gvh{l zrm2AZ9jTmFs82eC4?Af?E@@0iL!pfeECtHK`wY%Lwlo~^+Pn-+Q0lOf^XfbkIos^} zR4R(XR?W)wf+&(8kyDcWz+>mOCBQQc{0!;W8v^|Qo^mp^Q1SG=;e~}r~T?zT-y*cJ-cqWBOQI=##4T7<#7jC$* z6?}$3lagy@AIv;Cr1U^MeS<6KFU)fHT7@4KYWc!$!h zd$^xR0e)F0+3y6G?_*K8^xA^VZ}gmzd(#xfW3XSyiLR>W{a~9NR%Nb6>dU^$5s?nU zhkIU6M_K2pDl@{m>5_%*4k69lEU92@mjz?&IUK6`vYop1dwnv~!1r=@DsSi2EGm4y zg-xfj^K1N|NzcZZa_S$Tg1Yapvu&YGVWlcup*00zh#Yfq_m>bgof~}DHGDlX_d{b{ zTq@zpR^RJK%IIg+t~i<&CC=}5Hbv#(jviOPz>P5PZ)Udg%qa5X%Dn-H{Y$ zkn5FN><59vSuvj(9$FQ2!s$UQf-GrVS+99S3qmDw&amaZJfaN_W0uGtb84WJq@s39 zQda9-zow~{<)5rtzkbD17(_qg9_lzSOXk9FBph6q#QHI@7H<&cm!^}2@wUj13mFs4 zZ$omDP#K}#EyXoDF;&4VN9ajR`1(^Hen_yY$Zn>SEj#rye=Hv|`WWh@R4Wsh7&MT@ zu;}?@Ym`#iG-nabu*y!hWGelQLuyYBhqa^4q1Qw}lqw3T1)?=MiOQS3l!ViX`jAvz zB7wXCGJ~`+-;GD$(5tf7DfvLhF1IAVD8)pnpy(GeI66Usms|ru*IC$A zUa(G~b{ly`AG7iC>p z^++eGi@^nVFK>1cJJ@58ptIk+dqz?ybVf9@L4E40A`6%x#Y?11YkQb_?AeYpm&U~O zM7f)gj%;~&v1zDLN=$`k5HK*SZWxv6NNO2^ahS$7edj;MG z4Ulq>#Wr_KvP#$L6zJui%!>y;Ta_OJiDbVEpp;|OT|~e4)YUPwf{MU)5 zVY9JzOEW&Z*N$&_ezl6E;v_!9611p4JV|srA@P@6r53&2tzp}dc^KEWC=Ep_`MK$v zcY-siQd3OWPxDfoI!|n54@_=rES4LS!DKA|2u!-1PJB{ZJjAUR$6Hq>Woeeclmnu* zeeaVlr$@s}spsjHgH@EJ)B8WYo_}u>1DW7HW3{hQMor%a?OPWQxI#ZEYuyIL@X;nk z4usu%MX1~ykc~GzW6P1LC`e^=c4eF0V1AnN32Uz2Ztt?uD-y<#bM=@{#qw6(@ZXTHobe8wkxE2 zy!Cn7WfVdFjp+@Rz!-Hx`Z*CgYL@|1LupBz7B7Z?&xX7aj@fLy@XzQya6W^@o%QyY zYIhO7(dUk1oA=+~THnulh%7XoiWTiN-%F=r6jbI~7QNPzPiE`G1Vdh9e7Lr+p1fQp zc*b(RB{k;{H}-D$D)NjdWKa02l6U!yk?3ZQo`@#mkE)lz!8%!9Hn@P^&FZhAM;r+Di1)N))SPwc(kM#f?Pe392JXSW=cBbjh4->U7(dv` z;T*-0H0#RX_;7wy>3}?pgzE?8zgqPJ!~!1d&^PU`@_<_30V<;PMFQLR&DMgq2dz3j$G_8NQq#`8N|260LI z@PgDaGwQhFb|cH5wC@W2lFyj>Rb5{B!`x|Wzo`dZX`XT3tT=r6B@-G}Si$J>QODHK ze^NeB@WZ9GSo@^Wk9L;|$r<>xv6q9@V=YCzuM-~UAn(PY{cJrwU4_`$ojushEM3g4 z*eqO}*nP}g**V!b*Z~o7A6GLA2P;nsb1NG=XHlx7=5{IyJ4;b2U0!7lWmhRHTRV9_ zcPmXl6)g)t2Ma+O7+J{Z*OllZ*DdhcN=z2K|w)w4lZ^s zE>?&HtB0?%ri7qOh6X`D5zJG{74|7t{FE_h^d|a;6B7rSx0~~hpF~Q*W}@LY*=an6Ybon5 zx?7NMUxfS8%FngAhJQ2|P3oDc9exq;$-R|txs7iTy=K0RUceeGEbcw8Qxw z@?rvKpm0}RQ{nqCpXUX3N^zS*qd07R3k>uJua*fK)99FL38tNm6kPr{j`2dzhtyNluT{DfBqVq--Q42d-xjSL6!BpOuGBsPYdWpV zkY;U5+E~fhcbJKy2{Gq1I57&%2MPlC8<*CWU-%1X`WuTFO!V1X&hxu)l1vVa&tf3L zt2MU$5WWy-Og?T$=d-$1u0g5YvIOcAa~2suH|P!Bua4#58trHXY(-|wdp(&FG>r}> zkAmMd1)>;Q!!0+kkZ$aSvu;_PkNW_Wh8p$>mU~AvhF$g zc-t?}yD0aJ4Juq5;vcR)KKyJDys1hE6+fYVG3I+!6cZHJ9=$3h$1-P$s$!gHjmY$V z2L?Gg=$*xB_w3cWPb9{?e?%g6eOjgB{Ja7`U-gaW0w(RIIP@UNloZ9V3`;o;GSSZI z&>JJe+r0$cWFxd%?5Hb~2tPXnkdf)mPu6?6Wdv{c7BUsrT0L(+Bbng9<8ZD=;B@|M zqL}sB22TxTtjYZR2p?r#1F6a*FpS%K(z3N~XE2h&&T6g{Gj{EHqp+|Dbkl9pf(%AG zOmFz{FU!{(ABVH|??rX>k*B$p%Rl5;N}8&y-N-3Fytlw!?jB>YcW)ye-drvI7#gcx zg&@!E+h0a%n3Rthm{qNL6}VaOd{WLZ5z!6@DtG=Sie~XPTQ}(47{dDoG`LInHp&&_$(`NsOu^Ijo6GMNA)oMRu1FzJmnIM*zdwQdx=Hy-=V4k8xL~ z;bQ4x-!1gJ34yN}P8^RGD>1CJRyC9sfWUY7>YgLz%5XD39%V{n5W}rVD^kr^*Qx79c`$~0{JniIK zw$5Na1Mihkv`i+)%r`zhJPNee=0S$5;)&F0xcVgi+#>z~bhe+_T$3Np8MRH0gH^I< zYFr98ifIm-%(7}S{s zutjs@E6|bnM1LUjI|rp|r?`;VyGfRhYI<`fAU3P=m zRbA>5sKKi=kH=q9D`|&zZhc9PY}gfU0|h4N^ASpvQ*>d%O-#RcH|I^i*k=2{gV+O+ zhCs_G)+nP^aslCctpG=P@*l?^9s#m3v=k|oan}bIq}EF0!}qf(K`w=t{o=SwFz$ph zg1KX0zF+qGS}Epx0i6xM_V_RB9pMdExFQ(O5KsM2)BA6yUMulp@B&Tsj{xIE>v77h z$nmy~*(30?;x*~XNYIEFa*jcE{1L^DfmRs($TZhY%eS7Cz*~^R;=b$6GRY%=b~=ub zpF6Tq;avXOkNtw5wAtm=`UgL8(5Z~Dq~ZH<0WX#a3dkap7*OeVYcVK-q^pdpEbZlq zQ5+;;AB~*4n9NuA&|kES?7hF;?cxDNev6}W^wE^5ztgi9zMsF#e+O#}9+SD;3_;7Z zpu!y7ek7PiU2x-$>3hh z!lHe6J0|a#J@cy?5lJ5cRZUu}VscJZ+lEWko}0sE9hK_br2-vk`y-Iw(7c>z>2$?b zLVdO9Ba}w;`uRxr2!-5^Hi~mSpODIZ!Wia_cpUxf=YAzLBObd~JGD6S-=zc>tbg)7 zJhXf!hbECtrN!qOUJJ>JO#jYqyIy_H8`3&Z8#%C+vSJwX2%u_ytP@ZW$Utj8OQ2A)01s@IPzh6+$5n*KRCzm*x1~voroQDuFRi>-~}MM#h=y2E!yy7*Md`i6+x{?K|<$w~tl9(bz-0Dos#Op8;r2 zs{J7ESIC%04V@O9D$e0XB-bw$cRoc$>%Gv~gd!~$B3^lM%k%SPL{$U1-#hPKaS?xf zgUGe<6}wGTcH%8MV=+@Y8cK~B*bp-Zr}~A>kfN(rACA)E!qAjB4}^Rl|5fS<2DMoE zYN4k0Cd+$ug0e4QwHe>ZXiS_?YbQ$~lu?}aHXo5bJOT%iMsGTw)9GraYgvn!sTx>W z@|1{j`=)6N)!O0jIoy6~gAe0pf2&m2uGaBBe)jJ4tWw&eK3som@T#!RhdTVO-RQVE zr@gI!v^RS8Ayu(8v}SZDI2<7#yi>G-i!%To3}jveqrw+-6b=S7V@@Ao-2w4ITx+pVZQ%%fyB$l z=j!L#a>&MTKX1;kz#~8>CvSs`Xjjlcx4Z7@*jx>Ne*+vho`@XJt+}H#fyL;1 zyJs?(LQ&#f@V7xC{*yJrAC>k);$pI*+FjD%;?iOWOQWHl&x)HA72U0JYO7Pspz0VT zfrBds9`rt;q_LDq<}gSnf0oyQjse z6NjF~Gp@z1rM(}DG*ZJmAK1>(-c_i^TWDjek5Zx8oS_i3%l2T7W!l*(wq3Q6w!zPc zlrcP~IXI^#5%y_1Q5X@&TbwS7NiM9YA!I@od!c}ht2b2}A`0)}amH7*H__a7c)h5h zzLxMKKCtc0R9w_3hKh-?eTSE++ed^FFn)sYbS=XL!SG+I?`NrP6kzl=G5( zar2@}qOD^Qu3^XD+6({fv)3`koFDV(vchMsAqiX2;W@V6&hAx5Hy)^smil?;DdiHk zi)be5O`fqbI_zsm8r+T1|uLI~FKCc?)%Omge}r zN5F_$6@JZj=U!TtH<{R6`GT~r^E)&(&rAHY4!i}`nGM&{Qt4jg!D~wDjU-fYDlpWmr9mwhyZWquJ>||5TW1X86gx_3}S7Pf? zC-Mwguo~ zt;EV2wVJ;8*3eO8O0$E85m8JhrS#s*;1Sq&Wg>oO$3_D;)bZd{(cV6TW5k!KGkYqN zU$SYtft5XIPGAHb&_4`6n5n8tSrX$>P?1aEwcv1H-^+|b_1u%Dl=JgK>mx9I#Dv*P^#s*9u6qfkR>O$D^%f$&O~0CCkx zRIph@E{&Q2r(12U_ak6@qBS9Zs>s7BPh)k4K(~_hseW-a>4z1H6O92ADJH?(JB21OLxE@j$g@~M{_D=$27 ze8zptMnSCVmZg}_pTC17(UuT2W%vt(qii6dx2{cL@2YB&6}S!Lq-%!QSm~S#kRH@8 zSKXQ^Fpy!hRBKN0ysYimIhxt~W{b0|EzA8?{+c*zVjGFIZf7FGO@z$li1w~vW37LjdNiE|p=_TKDT zUJga#hZ%#)l5;Jd7>usIeRvN?4NJT4q#%aYxG2)w7kl9#;rbG_&vjX%m8vsKvr2iO z%@#{LhkZ6SVWZ2|2-=E;x3n8(?ANa~C_RXrL45mu_wDOs<>Tpjwi()=3NNZ}Z&xrn zxR`dOTg$~&&wJgjOLvGW(#28=WDbs8w*4`E84NsZ;{uG3_YVmTzE zZ;e<<z?{!5rQ=NAjm`Z64Rr@Dz-yE-4`rMToM;=1*avn~!Lm$x`%#H?7&<4#-pe_sn@H`LvNTD4H>|trbIN0^ zP7Cai1%+w>nVZ!i!q?A@)xl=tQNN6m>hAqkbJa5}tl7qi35jN?KkY0aN6q7zk0-uq zO7`P;U{8a(kYTYHVC<`rwZLi#wiip*x^Y@qZi6vMO&*we31g^Ub-j!;Oj90&GZf;D z6r70jqJE|lj**gSKTrm_>u>hjLvcF|To}`2qqyOCO z**w^%WH-QA3fCc|s`VzQ4z6T`NLR-?c&GP)qB8{UnV)Hn!58BaGoJwKJo<(bH9P;u2Fz*bkc;Dz7U#=WHEVe{5s zPMH>$HPA5qdf>}M*9N?hGg`HkFj-cDqYJ}8Xeza}s`6CHA?p+ge2<7|@`;Z2mB=1@ z(FoUNVj8;F=>{pn(JRk-MNph7*8UVxh^1yL-hxzrVf5w8@}sc!H#7X#xS5-aP1~L| zHXq1d)0F5^VoSsID=mGD6&;*#`sU=E>x;j}|BmE#wYrz2am|2ag(^(peWR?tJq5Nje(Zc$~wyofGQ;>WR+q1DFl{X~N$QRY)a0=XD|!zs0Lu-rQ8)&IX?5 zTgeI6a~~nM_l)w|CJZx$T@5tQw@)Gl3Jj|$Duo!%?z8wo#X27Menmq)(HvTQpDEJ3 zwz{DO)c!K4Z8H|FR7>=h1!=U)l5@y%*@vZZJWnoK$F=%C@3e%d+=4eC9}mUqR7v1UyO!qQ0iGZ%nU$8- zUBX^%?F^Z?a`6kGt#H7&Er1nOvMLj;*|5ANF$XpmCvc7Lh;Qn`_clrz^o1}!l#0bueut)ky!LH z(kN0X+S!%7Qz^vT3)=MeTq2&k-19=2l=<4%x@6^VU1l(w$0eL-z;ac5wXsHyWi&k^ zDA}pstJU&l$bN}nUDoBnvTMl2qHW!!a`uZ++=enaq6|5X4bPU+_ir#7{NV${#QX9z z_h_8!-Sn*Q;~V;l;<%$|ONSWdvcMXKqwjUcW|JOnEv&yWz%rImpHiS0^p@w(Uo`v- z;uBq+6&td<3QS7sTQUwJul3cfGYT}8&0U&C5{mH5NaM!+K+YJw5V(<0N#j|qjgJjf zqly{6Fl7x)CyD?g<40h{LeRbV}*Coez#sEiM4(7HbuH1&&p28 zcF0&cit46rIdHmbkf=|>Joa$8*A%~f&my9bfj6;GI1d*7Dthmc} z@PeRRN2G^4QoZeRabY`VY~Gi~MVnaYMJW>%`z`u@?@9e0U3R{lE04u~MzE_>-4EK>vVOgzPMEJv_PT5t65M z+s>^g`x>m;(#*`ZWTyDUq@tIQKwg)!+Quim3H;+`0gm*o<-|$Jd6#9Pyz&&&(%0g} zN8q6ds+Ipew!TrAlTdy2VbC^=Do+R=W}$U!*MdrJYt!Y@@?0+}O)RdwUX=1w5W2}# z7_mZ4buzK?*`PY2O|ncLrUla)gTtxX<<*I5PfTbJ3qFh{@Z<^7;nB2CpECFaGe7cL6I_s*P}@*hQ^R5R*& zmM&T^#3dt+_>eM;p6BEmV$K9+ABEMlG(EowFGSPJl0^0ssS-tYV zQvcdw;uE(@W<02B2oEz}e*k7EiFUg3ufsRCCI8q`u0dP>(&A2FuP$LVdc{Bx&+ikO ze_IBwv1cG|Fj0luXS86iy`wkA$9cyt=-~-yQ-m{^n^VUg-m%hxOMYGAOX?Ei3EgV% zgp-Ikt@kaH?j!gTEp1Shpqby&B3u$&FVXg7tvSYiLpppfJMm)_S+~XJ_~FXobXp{n z&D^~{jf5}b?dL#DhqoE4u)C(ifAbL z*U$Y`Uaqe@ZISgJ`D;@?M^_$a@B4K5`biZ=%io3j@Fl|xo%*MqMwi0EGHA0?^Jm6b zrb$+m^VP)9em#N}!@M%=9AmI+bnC7i>mj`Na9f$dPe zSWWBUK#LK11s?xdP{r>B6&~9XbR2sOFVo@g@`9d~a%Fa>rgXRPtLezDIwZBnMretR zb&4aTlI#VITJDxh9!cLVEO3%#++*a?t6%8Q*^)A7z+_iuH-!{C+BjpVF|mkij5IVx z*%oJ?gGW=j@Ibl5Nxl6e2*C&AxGbX`?_`F^+VeWl*YNqKSv)&O%5x)6$;~gH$;SI6 zcV+o;2iR0x-$kk@yRy>=2&H0E4RWo5#vBxkwWjTMEya6Ihb-My8%V3_Pe^6KtYc!6 zji7J7_r-zn6Z@>b^qnpp9k~UNJ^9<6;R~uJ-{h}7yy07TpBywX38xC$Kn zFnK&rXQ!Htcd8R1##DT!z~Y&}uDe|&F4pRn)y99Pxv_+CCw8LCMFUQ1SSrOI7BESc zCBG{loF3}+dmF8gnxM!)-osgv5XMg_P@izN#C7uN>&@bVaHc`&Nd4=j8gC1At)mJD{Keqo>ebSe_aAE4(D))_G^2`7(+Wn)rc05o3bEduo-^1k@xIY_NHX_A zOWUmx@+Gq!m${cy{z))4p=vOxD?&yP>SvPM#D|(2;59 zNV5q|GW=rhF3!=h(@;L<{UsnNB|hv-oh>WdzWW8J9X7Tfyx6n~c0U`7JyUt%>g=Ub zo1vndCfi<1S73_b#ihVt8UEso$_tT}NJ9302o@4B9Kppg@CDkkof1`$ZIIyex=;`%`XC$CYC8&vIGNp7 zmW>ZhLR%x0d4#Og(ALGe?<^Q!{GcF?NUT3TVp+#-Q!b|f9d?a<{Oqjri9rndfw;`{ z%xs&Vhe$r3Q>f<`SFt%SZqSc|`ECn~7)U|^U7W@;f^nzu@~ge5nWHi+^6Wyx1pKca zmu^|blNZO`ogXAS3B4&BY!VnhqiiYd8r;o9?-XSlc9Zyl@EawlVbI+JPN=qvdOoco zuX;!NyyD)D41d5}T}%;(LWzew@3e8tMx_+(z|jt2YR9v(f9NDzOF)Z}PCVHmi`P5aop4Al?Y8 zm&1WY9N4mb^)&f2>(C=`jvpoH?tfph>i5&monbpPvpnZaLy*YIChmnss00o2!JF^L z3oC(wCuM8&>C0Gbepbib3Q{`mV5H&idflq}Bvf?C6hF)hqDSmsjj_ai=lq7Fb+SnC z_27{8u3FKse={no6L#g5+;`DT*ZtJ5!H_|dVX6K~OCO!NQc~D?WkSpP;M6PIz2LGP zA(VZ5W@A~OvSt!K7i@{zwJ(p)kB`02YB5>KjlNda`@nmZ!n*?2y3*NP=C@pJ!nv=` z+MYwv zxN>O*n9>!0BGqn@;NVNmPEdD!A5#U57}b@#mX6hz54-{meB#}_mHgefx>tUU?KsM$ zXVM z^qw1PEYGhmYTunZlzLvY^pQcD>oy`d1+?mim8Pf{tk8Gvl{AG?gpiUM}&nwg$)CHXx+^e3# zldIzzKAXpaqDWJC9znq%mfGG}zmwoF)z3^dP?J|Y)qz}lxqMFU7VGF#5Ya@Ft2U&= zG4MLcDd-(ckFgewEy$oJ_h8@USH~b*9MTMCuuH(;jdv%<6ji@Er9{$$)q=a5@#sb3 zyn(F&?HP!sB3Eyrs{WbVexQ54+YjZ+XYsvFvuh1sISc8Y#S+;4s*O7e%z6YC$gR2x z!F~=8m{72y3dJ|!3F_vr5}fXmxu<&fQ~yIgF!?uyLJK z)s`a@CAM-);^37jJMi@r9#VC|8kQu52VQL;nTddJ!b(c!oOCUsIzP1T(3cFbF?0Pp zu00^Pu_mN=_8>oT!6ooU(50`1_p8{84UvHrrTO;)tL0m;;CMHSd{0kPKD2VAs!RMu zz3j2c-b?CtG$ULOysK9ZvI@*Csgi2)c8Ut6)1bPtb76q5j$ibc=cH3JahsP6M=+^J z{#wOJo%r}yieib~?ogGMnm5sR9qKbo(yvFGl^3^gGw=={U5*I2cb7-lWxNCCCl0C_ zZrL_}>Z*FxoU{s;ezUxm@v21Rs!0~cbc-3kS}A?EI#O%caA(?6n?F&85ucl{ejUtD zK8!@?q)hahndY@q>2}a&0;@eW@jK`ES4gxy*wWWVSPgnaRF>u}Xd%=6I|*aMYtd_D zpL^cDA>*wa-Xkib94=jE7@F7&j_0G)3sA|cHw=rPYjO7ADto(xD>&0%_5AI19G@aD zE2GWiBQWs6SAF)Nbv9AxARe}nu^Z=ZY5PIXfpIYR4As~rotN&*8;?g|m1}v+B|*ZQ zwF|9C=U!opG4EjT4xj$u691S2lfP26fi?J)KFrof@m&kI+&hQR=dbnc32G0Djj$Zq zgNlCjsZ5N^PDY9*v#LZhXn8ZeTsM0(>VQF|<^ zyyb8cr46uFxJ|hnqD>z-`l?fnluGDSQxFH59fc>2ly)p8y)tZVHZKvZ2~T*ieEU=1 z9HcHgTS6Lmb^b;H>tnD?Xfo>Iv-!1Ix10j|R!(YyLzU!y>w2?;NTl))E!AaO2#8Tb zP1BtcG32tD1W->>3hdMtjQTF zR5C%ti$H6|cUVv1c^IVRo3;6t$E)`3xHd}{t(|rUS;69g^Q~be=V$dHyt>m|*`eJW zRPTnm-oW~Ybk+@DGurew^V3J|r=8dx@g}F(RD_zA@YH-MQi+WIcI4*HC+@I} zsHsAvXN4v`-r%+TYEkbIVBd~NaLAO$)A2ezTTNKk&1`8{C9^%%aXcOx>esi? zs2A{r2gh?)W@j%1PH?+Ptk$GbeIEfh_wMlZuxR?cuQ}?s&bc(?k%bZjyQ&Hiau7cWy5w6)V|iorMyWe25CR-eb=5!G*DwKa_GY7oQ|rxXL(-%=!R3B+?uz zBJ9df;>OP5Q97_$GIIK%aa*Y{hDxupx++r+0s82t4!t?&rw?U!5+dxxngupApAn0u z+uRI_p~GQJmMSX6+h%pSug*`;IMeU~pKqyaGEOoP=2|yAPZ0 zU0(+W!s~NMM=evyS63bS31lV|HWx^kjh}vkso-D51(lXr9fIyHq?-US%NK;NjXwf% zPmp}1%bjaTph72^a#zk&7Zd37k?L=lSu z$M~I%*_)|mVovzeB{#=Q!#zCIta)+9v^R*E3~-H_-zM%`>%I%lzB}F?vdpHkyCmiB z8RmJq!p52j!p4S69i%0;0NdZ?d^=U7o$PFEWd@H5@4i&{*FhU0_PH8@}d^@^QX#;mA-b(T~E8hY@@@bmbZcxL83FFQGB{{Xc4M;2G* z6H->u=6TaItP`S2@Khm-{;IM@Nme#=JDh9Vm_HC+H0Mu?j#c=S=EW3Q#!JIoL6%q2 z)l$g`Ut82cUMTi=hE$wV{CO$bn5-X}Flki-@NL@=Rnj@`V+Xe@v&HL@w z506VWnlQ#NIJ@g#+&P2>X2@>oK)BzUzZY&(@DCXC4~p_WLN^O=_EA1>nM%31a~(7a zUP4nyF8X$`?{1j9zYMPveklA@#l~EJ&FV~-BIQ*IiX5ZJqG+VfvnH`~8=kPhw$w*g zkyiebhL-rz_#dlkjGH*C;>y|zibsm38FJQZd+cw8DLyh@1}M@RY_m1u z9KMR3o;V?oE-|TFDfFmN2UE4XVLF)Pk%gWJ1oa>Ch&`=8S#B~24OX=-5r<3k+pY1T zKZ^c;oOq|_Um-pnoSOVLVa79ONyI!wTVm1V&-i&247L^t4Lp?h{C$J3czz zA9zEBGg$d2lIMJX$1f8{NhNGXo`#-FerXtswYNGz-qywwd@j6ccxdIX8*}f(FN!W> zR7v6wiZdU>Lsc~!$|B3zR(gpMkw{jWZ3@HukVXdAzPn4pwJ{SpZbu>O{S&^G7a~_q z9Hr$i268`@{0qt6UuDNG;NBj~qRS{_Kb_SFs#y>5OCuMN+q*f%qVa*^M}_<(avO^| zznvvLc3}#w21l02`hRL>Qs2so<9#B{Bc8~O^2Ry0#p}R~^(Z0c?8fdG6PHW{z0ap% z_5T1-h*vT^dwecA7500p*JlQBC&vIi?6+6kKGaz*;ticpq*w|xV4-C|J zfzq+WUQu}MBL!;w{CxS548^KBC%~0)wf7ZLZ+(MbN#6H5eY@>~>Ha^QT?}Gp@cF`z z3A&v%j%$&$1%Pkrx-V~OenYZj)df5;bdO|Q4uAJYg*uQDiSDW}z9*S-7y0Otfk0+eKS zc{d8*l;7Lyxxj-)lr*Jjnl_DUj6?x{Pg8#QagJ3*NkX7q^%9?#ea-&>m$zIEI(emZ zLmd=HOlqsOtNdUfx=^!Z}jK!0!ikz zOl7U1x)Il~_rttdHAIk9$kDMv`c$CYpYoIZE3vuzU|#Peqkx#e5rJs#;8W zms_Zfk!;;;01f(g-wsu|R5bc$j$HwRKa}5_MYaatmj3?M_r!Jrt3U4;uBFtaUt$kJ ze_gP>feQjX;{Zvawu(?U{ z!fV{unN?6` z966a&R%O-DIS$aXtH!|lfnaUWt~a)TRKgWjH=xnB}|tI~?~W ztDYVibIF1t#Sax^(1J)^C19vk-~RyVyf15i2`9EXgqJC(mPU~IcRu9f^TW2hALv|4 zT{svA9^;U`g}`;gRi%=-T%TlH>S(3yF8FDBeKw z0cTUrYQoG(kN_2K2d946SOr+iD-s8$!{yTWq1GtliQ#fC)=*8(n_F@H^}@0iiDEJ) zjcKaD?ks!b)aE~D3xP=ABn*s*OH57e`N-}%eeeU!S~*Hcl6#KV_xj+Mb!%LeKzH?j zTp=TCn6PlDKo+>gX1Uyu_?XJ}ngcrAv~z%TjRSIhuQ0gv+e}47{ zt_92F(K=17R7T>$-Oj-Nw!rdQiK-EN#+}%+u{Srr&*g!c+l2(J^bytBxK~A|rh+MB zyXqhiN$%EHHT>GE&#%u8pfi7k6*Mm+0@v}C2!#Rg7 z_=7P_x(XPQQCm$T)YQ|Yj!5#%W$74P5PfTmBbflEcNbRDB)_-&^uUI)MxBQ13C(Hh zl3?1TYI5}MNU{^?U@m$enK)7EsGe9Up;k(^K+cW14WjJ3{K5KgLq`ebsg{;z zhE|SQSrLOTLK#)J_Uokk+YeceZI;*N5RbvFE@-Z{mMtp2TBWRQ-uwN&ScV4F36kSh z!o#@w;*eTsO0W_to8MOVJ8m$|mMus=Ng9j88tM#BMBe8V(7u^9%Iz5j&9~)TD^U^r zIg-JOkh_1BkAI=Sw8Bq0rcz<_T!2l@`+p&XT@+O3|^@9hb1Ux9f#co={e1A*3V_J87}s4rmo& zSFlQPim)_eKp=inm$(=V)Cy@76)Q2ZKP#Pw&mMQY*r~{xJn&y#IJURT|(bg{#Yh9@)cqeNTiG3bB_d`d>TAPpo0_A#xuw_2j!=7pbi&0A~;T)(g9?VHTqAWHy#bThu zLj$5jZ9wY%a56IwG05D46pI^eu-g<3jDMX;APbKF0QtnWJmo-kZ8)_{fhs(bD%hyE zb-oZ4G6=%c%PcGiWx9vnlxc*wuI+zoe|Nx#S;CiR zDgG+zuoaB$<^f@?&&vM**A-8g$R&1)S*`#E&PJ4zjT zH9J(j+-lRho1KZj(-*43E3rX3#hBK)Bh9F38q6$hYuu4+Q6)u1YC6k16pc$Nz1rj- zZl3$#8d*^!2T?{LwF~yOxBhq($lAq=Fc%B-zy2_g&n1koGMplsh*hDQDJrQwTH^e= zw(F>T$ifn|LF0HJD-l(`vDJXFAbVc;@f2#7S(YoYD{*1A+x3!_>z)2tj36Z;?OnHwEN0VhW z8MO1|(oYoeQ%Ou8Q?MWs$}CA2U_Q8_8tJmu$|Y#&hFW2d@e$2ta^IQL%iCdf0Q-~e zh}8~f#dMQN#5v@@vvWGw{K{H&14L1(c|n+U)naT9O^L%(%_UG@I$}T@YCE%7T%1?j z=iw1)yDCjln9!_I)>c%8sZ>D}K2SiHb~{^RU~W%c{#Yg+E^|n-Q>`Mw5n>ZS4I^o> z1f9+C4viXQXhr2u%8T_EHW&gmi9m>M#O=33ZN9j8jn$QouBzkLX7pLSl+WduWU$Z} zkc@6WH}Mg-+iX*qmPjO8 z*wH~TwxA7xu^#sR_QUXl@$$_TKbelxia4vbODkaKxrZGnvL>*=-j4n1Kd*AwRi$l-shCKfOmK;Xy z0@c(}GFBiSrUY4BA^smpxjj8UOkD&=(CDpZTXwds`V-t<*jGNvq%?WTg>4DmLG53$=&D%QT&1Ma!wxX-FR9Hp-Wd8`ZgPxC@fTKq=&A5}+N9Tr!_Rjb-N_{-~Whqw-v|{{V?1x~SxS7$Hy>SkFOy7QgQ)2j==I+wa(8Q=SR5 z!^?gnoupS;DiLkC0_<)H>NoA~E-|&w@g*6lpzzN^6-;kWoHfY@OA3m6f!to-d}=?z zFq*4@c;bp5Fff*uWh9Lti6q>6cL(kB$71e6Kj7p0er0oR^IRVHdQ#5ZvRQ*6sBL6| zc0zRbx6=-CRT*Lm=*ti!CHq|a{-*)aG>#^43&(v&(mq43D%qqbQ`j2%hBn^)?~j^Rd0mvXw_>f-SZ!>5`}U1Dwh670%u#so@T9N5fKQ+&#m_%N|@K3p&AAEqN!FHFVIn5f)#}LB_N` z9o)9cIjQ4s!xsecB{J4z6!^(LF)MFtkUv~umx})YgjW!9bHcAKJW+C!jOw|m z!tcYGZfC{xi30hVYtIC4C2c7|>Z4YW2S)Wq2CI>%E@E+C5@Ztm0r?e6HEbc%i0PrJ zL~tdilxLZPeqHQA(0A-_-wpo&0&f)DLBu>?#hwd!k5JrQ%M9-zugo%vD#B(;281Hj zQmAf}^FcHEKPYJSwzG{SGR>#c$uoLA#E&tL`B$W5ayg8?U#^-&xIbJrz1_U)NYB?v-uqhr0LvacsBIn0 zXQ2bPw)n9`1ysCpOIM{kRL+!5Dp6lr+#8@f*pHV?1gSExxpz`-K-%DR`QXSBH4QZF zA%%~YFW%5lp>lss!1o-)Y^`<7q?Bf9W8tH?S*EJ zm1`$zN#1I5Zp5#*{Mg~9IUYFdy4pRB*R}TF<+c}!q^ueQZme!^?Sq(#!mz{UtCdP` zPMWvw1(%`!09<{mX#xf}01KNCZT|T2WGv~`Kx5SH)87gZuONU;Cb(od#;`K_QeYc1T0EI+>pz@*4wT=iVBK~ zl!Z$@M2(?Tn-bfbTWzq{Nnv1kMM-suPLwPag_!pFU;=6crZ7uH5koL-l>Y$6E0}1A z>{?S`6p~Nd2BZrdRR!EO;feRRzv`m`M&X1-QqD?9k;u&De6MSE{+L)+8A8(=c_`Y) zr(gi}ZLPRJY*hheAwsK1w|kZU0DLB6C8XB!liSuvw{S5O8h|+RMNrbk zSzk#*JBU(gl{GNgbue4E$X^6iGQ%}ZI1N=2O2`>@Hy0N@x+vf4fjq?l3|A$8KT-+B zGy3#w?HMGsn__;L#*z=BWg4~Xg);e|sdB7A8-i`yA3T;x!I1$5>Oi%&?fm}$OedwD zGOAK2?nu4*9@fH}hm11`c57R)+j2hmi9HnMdXg2VWej|<`}^;`uY%*cA&f?%aBeQW zM`8VNlWHif`_`3M*b+$T{Wirw$l+uN`pEpmmA&@F!rWLy#H^3zyo>-+djosh{Wij` z97bLgif1C)7;W|X;3-^ruF9{h3s`Ta*6;TIcs?{O8oQ>IW*cp5eC_nZi*K4D(0QpQ zOP15;97B~sUr_mOUn@r(nnlAcy<~l_*W2%pE7vE^GmP$f$(pk$r>T)CGSD=mG6iVm zkoB-OuO&`-}KXC(Ze5z_M}NnS@YG^!!0bqg*Qrf*vQ5&Io(xD8tp)6&bFG zID+n9uf;IL;x3k}jB?Y|&rsyj&bKj$`&<*a_PDjM-i4N^ISThX>0Q0{9@xpR3mzSK zzr}Yyd3VU(56?257|*kosEso!_?@AmNa-c0W^|0|eW7Iv4&;v5*bj)`gl2K!>yw5lFAh zrDK1~N1S)dt}X{qbG=OHNz3I|;Grq!?O&p`S3Tf-ItjZznL0p=GC$SJkNj z)IGNsz4qID5+sJJFNUruR%(r7%pe~~-oxkI<0CvuczWYs2Auce4ova-<(Zy$meRqd zzJ_A-`J@#P7LKI@0LmFy-53I_q;G4Se##=EmX@|ERYZm}D>*NAT|4O)>HsPSxw*rj z)CUW1B9|#}!9qt6f>`3HKns9I=HMS=`e2uiMGyc1)Z_zu78g6;w@fcnO;ZH3QPp0O zrawuJd#j`Lww~jq{kH3Ygm)0e6%5Lz&vSJk^&dXJ*um}GQU+16$nY~eF$_IEkZeHq z@81W{n$}i5RD!aht0#A9ST^%JD}H9}*57N!$MbbTh2{R#QPimrUZ802sAoiy06^ zs%{xol^L16Dv93UWAtX^+;3aSu1!}|)X-Ga&%ya5(#Z77c^#-AW@EQKNQB8DzNnY!B;>iQJ5vw2b#3n)q(>8MW^t(P!p|q?$0$6nS`D4*h@>~!c(h5maOFLg=Jq`Qb z!yY&)8QF>k+i`o3mOPOV>Qz-Iasj_gQ|c?_%q+WYd-ND<9b$?XHz?Q4sf}G6AB9sg z$KI}B z%;XI0s^l^iA=Q4J@w;z_cg7Elyf5Sw+?(d*1z$3GGfstQ6&M=ah!g(+P9oM1Pq`vH zf}80!^x~GcNjHk!OgV7D9%IYipB|tF7~R!s6?n6Xp~~jqxj3gZn;}VzgDo|z)axzD z){yGct8#xW?nmp%xd40w~2FUCGLx#^Tva3(`dkyOy|)ES&6o_D2`E7n&@8(ESw z94j1QtX}Tc14%g}m;6dT6*AN>F(BZc8KmQ5YL8zDD%PZy7dpg8aevLK+jYjS{vtmZ z9RC2sUkugqgOeFHYry=nsR1kIpVL*EsQ&=zvZ*>DI}^U9*laEcYK;1}eH<{crGjkM$l1hBPErnPk4@8da*7^-yu{&7gjWvkQwIxU`V{fN( z(-!xJ=;W+Q?j}`^ny)Y-d6{Gv09-2V?Q_=`6x2^BVIu^7y={MUx6opikR98TCUyW+ zT1^M@X&~KibJwM@Okfw&A`qmDcDermTvszg9itK~cTmr%w>U+_T1gf+04O72zie$p zq1aUmEa4MTIFcx-qExb61=Y~s{e~L@v5n(vnHQ<;@*m3rYAOq~kt-I~dXMM!#c{|a zPc>u=&Hx))#1Yf^{{TEC*-wj_KT*>osv|-{7d;2t++dK6EM;0#*1(g~pv3?wjU#OW zHWpuF{{S6v@&}4H0hN7wSal!y#c56x2udVN98toTbqnb??}g??jiZzo9<3#>Z98}V zcfwKW^(*QYx9NLy#d64wR3Av{FR(qj;#zS*Ddb*K>rkKq9a*{p8u$G^*g@*0Sp@1s zN~cf+9oSp?b;8ib)491=h5bcHZLEJNHu+##1`YU&oD z;%K4@ZDaY5*R8&Ic@o(qK5p!#dSBT80HDPb>ZT}_UO>t%Yj?i;dtoMR5_w7$NHzhN zW4`yo%TGiF`K0%nWQml?6i`gn%OKi7wnK6(MZfcea?IjvhP5iAMV;(Xqc+nb5n`== zpn^rPv^CPxPzWR_`lLyt4Y`GZV9WF%kCwv>!Z6{ZC>57~%g|q8{V;4{Sg2>bY_S5P zw|yXV7_KWupxWx!^pAZ#f7cbHl9JJZs>4ly{HImFTmvl1VXBQh+qw`tZ_}-?(Cwu` zDn*mg{?*Mg%(L;7d1O@+BqnKz5k?t+)WmOLd*Z5!VM_Uh3rkHm;oalbt?8FbTIza` zZE?2Z*k-3B#1*4fCd7^Gb{JH7fHZ|r07by-Y!Nn7LvX4tvBCnD5?;kz0tNaTkLiUY z@=`y{&R7N9UrrG!hF>r!E7$FFzA6GXDy%L`00Q zSc@BW!nqtE3YTY&S(%}BkT#Niwj&2pGQ?w&AYDU{R5wsRr(9CnDx;6fGA@y|hQsTH zDPnY`l3gws7f>v2zLD4U>4~zT&Y+ib6QxA6w5FaEYKb?oaG;xCz0Q^U;@WbEyJb1W zEc#)RJl0oY#OxZ!R{Pjm!{i1oO?4zwXr+;wjI=gBU6^{poyk8#*RCxe57jnF$NWXZ zvnowVGJ_kbKB?k!alNhSaka5pW00-E^$P5}z>ZVSnhye=9kQ&ilYF}Ir^&47R?Sh6 z%xP&e9tNnAvCNQ{s$(4L9p)v*hmPZICiuL$cPMg7Zy8?^{s82Nn>^36E<)wB3zpBA zyy-!mRkdVdjc1vdqFE`ML2E~^ur?f)a>vA9Ir&kR*5tgn=7$|{E?ZU^s-Vj=DQTcC z$9D*=YujQ*`*pzlJJ0@e@Gfti@dpTVLymZJKg<9*jcpcXEK}DoV&lz_9Z%{dy+rT6 zHFEGLypq?|`g(($*H1-m9d!(ayg!GRfu9iG5!c-hD25(Em(q)YfYfoCz zy*5uElKxXRog$?Tk6l|{#~1tJIm(`APspxpaSY!N-bZprET_*Y>+3l0Eza`VjK*l2 zGt;lii56W|4>U!=B>wTi2ORNK__y&9nQ=c2aZX{*UTS6>O_U`>Idyco_IB(j18^| zj2xUcUl>eWE`a2E6aKGWwyQfB(OZv`vuG&{J`S zeVk?V^=U7YB6(sdl)ji5uBPJpjfm@wcyPxacwpr3!t=m<-Yhv&pYvxaIfoFoT}??- z<$fBnI=a&&vf4xssSbdS)Sm;NY zu6-4T>#UPp)=~KJ@kIxW9})aT&WbJ>kB2e_qNK|5x(0PJ(^1pLQ4Fl029UG4J%*s8 zWxg=F8fus-vqMYe7fIwtd+bHaTiA5A-NyZK^Hs}3K~Y)eQ$?WZ0hs#9765*r`)qMt z9Ym*v=p_c7%PK`CkTtfOfLtErTK3rNalF#P)&R!x3a+KsZamU(Ekv=Y8+FxaompL#3KE zB;2T5198*8d|Z1#%BKmUsidw{Sec~rWnx1HHv-4EzTe*XcUjtRHm%a}tWq#g+Z!Vj zVm9e*?}i#Anl{XmH4EpUjzSjtR1j_;YV{m_GLDx-%{+na-Zb>Tgu4m@-)o`$X zu~&Fsq)6`!)LGM8u(ebKTl@FMsJswVeh-8=yUvQCNlIV~3j(F&0NUH`e@ty}{7C6r z_>T*<6F{UxNt`aOyPBA`BK<5qv8!JOD^*dzS-jKKERcCoQ%0nXLqyNilY3e1_Qyr; zP!{OePf&hqwllq6-{|qv{1At);{2We=H&kG18$~_qC2M1_yFTGJt6%F!N&~HY;n3li2Nq>FOq- zt*EG$B4`#p4xxWL>9DuCw%8*^mr-RxMXX2n?}bEdaPTQg784%WqI#_Phf z9H0s)iRr%&3^K$?TgZ)n;VQt`fza-7-RBKx!V-=VQ}Xq(JCpbRSY*v=b1aw6mo0al zDkqMva8!QntX0L1=J)pYIA(4ps-dFFrp;+1kt%7#iRJ3*9H~-2&9FOl)$%w)b#4ZT zQ1~w`Q+KME68CgaG@n(jZ|%N3dg|HF&AwT*`y-5VRaHRpduE4^t{IQE+-#vD?_;h3IqMBC3J2S8Xu60Ey`g z3ApPcT!GaEe*j$0z{thb_I#ZrWtY~Pn%{S7~!9^UV7))W!w2SY* zVbBe*QITa};5Sa7bl%urr$O@7)Rt3VzW)F$HoZ@l0b(Ir8xGg&jer5Iq=W4oq$hbA za_S4Ay5H&jap{^xV{%L+X|?)dxkN0{ly+rfsC3x%wgzU3F>=MO-u(@Z6+@aWpmS9+ zEX-kzoF1*PII5rbBSx^%fJn9wri}z;fw{OB-|~-_d>lNotgq=kdTcBYe{3UpMB3<- zjz*YyVGY9zSdVY{!L@Lh43L#wUX~Uc5I{I>hDY++GK?6XS53XQ`(UW2iRxQhGLGyT z-}&~yND2pF+Ns8gqAW>GBy0%;n;TyWEPC5kmzpuLU53Z!?~fp;jfCjVSy{;h^aHjI zO(rWv8wF4W?gi{SVp^oM9F&j|!x3;v0N7ZYkC)FBQnl;R>`I~)Tb`}{xDt6@I(Lu& z@u9lhZV5KRltxN$1B)|m!}g1!OX<-1=$l^Hm2Fy=?pbT)`E9R7Q32Lfho{()RBESnB)D8WxGE5uI0EC>WRPz*c zQmWC7_x=-q>E8({YmYIQ*-19&cH4i~3OQ$uBG5}%3;Ta}!fu5`LOmqzFKzJCHMYVX zr7E)(+Q=M$J%B%4Hct|nT3Kacpl%4g!0+_IlInE`2-Mv#(;q*UbzFdeX<^>jm~5LX zHfJdIrKqNvAenrZv}BM$y08qV<#52^5FR+dD&pWXTYb7)3COa%%OKAxUgG%O4*SOvDhdw2J~4b14I zpp__ODJ@V?TJ|=-wYrX*`;0XsxLH|VNL&RAVQZaY`}WuqalQ(bC$BzY#8?%Fyk^y_`@ zFWcV<2hpbA#b5_+y+581UC}MJl*_7$P(&&sAHD^XdoG**0KN@LgmJu4#FDVH6))eR zzssiB`Wc~>VS%)xE&Qjjvfku^eY@d5G3mqlfd|q-y~w@)0MiVQ%%%Z(NUYOKG9sd* z7X%A_QGfTvs^)%ETJmN2-b+yqQ=8Ixm2o?QKN97EVBak&-)oKUi>lH_(3!*eE(jV( z+>X0jwha(VD2bp8Au$-p@`G7P7Z$PX4){du-N`;FOHZPS@V^vL@kUz)XOxwOLZD9@ zHQJf1ZiHL=1bZAwBqc@ee8cJ|t^Q1CR+8J+!eJ zzlf2F@;)=9&Zl@Kf}W1IDJ%p{D-cpL*03Eu zM+_4JZ6(ptMvq*6XkYqd0JkKtQE`WAcot`YU=lY%cl8dNoHbQfWqBkEhOv^B;kxEhu8Yu%jZbz=EEo4ySA;NW4w0u~fAO{%X!2-iWm=kZBCf56pLT79 z%NuXGy|7ELo~BL01Q^X6h7=Vnc*pccz2-u69RbtA4 zV{LnBQg;L1*pzU-OGTd5Pf1sr!;|@zFqVazT&1qU$~J8%N6%m}d-!ja^x4-A(DA)G zQ`S<^LmV~qD^{^h_@|xQP}OTHLaOa+-Rz)miu#Rn05(%J@RC+Eqy{N~sg5-|z+-W> z`=9S@I#pf@3i$(h20D3V4qDnR8<0Wv8bP@K0Gwt&3i8V%<6a-)TKRZ-wWy;qR#H|^ zN>E3nS|oV^ys|mlN{u(}dg90NH!rGapvkhBXpUW3RYv)JTU0QWQduN1d4)}^qs>oA z-(!tjd{M6jqndlP)Zj|ydnJ~ZK4#A^;A?90X)9aGP;Y72I6Zpn)-QYY`Q!A);b`EX z;Qj}p6x1pp$a2VSakiRBhW8zI$L7&b!gZNnI;Y|31UjJNDvED7p-Cz{xkNe;-r8?( zNa%0dAEOpm!(2?+K1Ho#)-w84A*2L?Awgqt)LPi`*LqJe2=C3`g7lYSVkEn7kX*%o zi32dMlQ8hX1zUwE5T(nZ_E7jv$`625C1P^&KYv z06~qIe~B0W0FRmYV~vpckCta7g4c+X&@n#j^p0{0DLx3<`&kTlHgmfQagUO{c-3$Ic?J7vn%_^K3h@qmz}(#+=6?)xQ-Z0W z&7`BwYUP?9C7}}}bN(5miBY5pBS;J^bh3cUW;oO5fzB!9zYF-QrYs$p0sFZXk`vJQo6r~9SeB*=eH-SdO2#+im`l~i!0 zaato?7>cSlca^D048k>(Jla!Uq6+Rt6Fic(R*3mx{y&#LxmGM`8CJo*5&r-WoXeHj zH#n&LP4fdN<=t(2<&@dAMsGmW($1lYU2gydhKB_~z0iy8i*3puf`=|Dd3C_q*N8t5 zxrZ*flf`hX`94)fl#3KGNB_FUb>^PPV&{HKP@J3i zM(3P!&Yu>%rskJ4=y_+Ca;@lMuFq30N$Imc#WOSx7FiHQ8$c3W+TgXjUl`Hj$Kmgp zcsZ)&#Y{YVk@H`dyj?|6U6SVXwEjT`2@xcPkUWS#>PF$!tk*pV-=Ll#@zuzF8s*21 z9~3E)WPHoX_`90fZwQQzK?c0bE~Cn+;Es1$Ln}tbCzuBWSdQl!Iq}cqnfz{Ne4^k! z6yU6WlQ`JclGfZMoi5I3Y6<5-##`}SZ(@Ck2?vPh2{{ZB2{{Y+W zLn&iVuzy$iD@ow{;nU7<6C4B19(MA|qbA{un}Vq-YCjQ}Ln9pWt!ZVNS{h)s9$<)i zi+V?zgTB_QgFGE^ml=3y=HH7N3G!UOfH+4x%JLeTc@@m{^%a65UM)V5BNM}@w&%>- zzB>@)24~?T!scV)x4@oV&RR-NVr1o#w=IHk9DG@sW>iv%UaV*$LdIDg6HwAtF1EHX zCxE;b@z*qd7SM7Jl>9@$nMV+3{M^nnY~}N6$s$PUXmc8hIAU)qH*Hs-r6ouL!2K~w zEqlzA=FlWpyEpd>9`yG(7IX9bKQ+%Mgr5m~!|`p-440FfwT6W=IqB*vYb&cutsYZH z3WD>_$QbFnMv9|$cK~;_-Q@?v+nwC%@jJ}_01A06XAE%v03YytIi%Umb$d(r2&1B? zNLYr9GulR#N^N@`?Tztx8s)bnz8;<%GaTcdJm$zbWzOzo=2ZwYSSllCpv$uA{{Sgz zp=VM8xk+S@k-3`N6vfwR`ETK`#Qy-rx5W<_h_l`gIZq2vMM*|SomiQ@EKhuci-vQqY3G!X z=5!S_RkAi*Xx%1foux5`SmPAZ>pD${QPr{1ZbQtDSaWZSeiK|L%HA8K;T}b2neKnh zSzyd2f5g$%Ez&m;KyOssK-4_6u-z|hQPfH{dIT@F=lEh-z>cO9{3X)O9d3MC6~aKvqW z@s>U~IhPkYyj1h+nk^t`GoCEW>So9N$T{-1n!@w{v$RV>O$>TGT?^*bR1_fW6m|VDLP*aMTPgs>uD|Wu>wu&(g_Fti zHCo?Kx4srxJjGThRf{kiYN ze(d)q)*m7D!l@;KhPzlBgVxwAG%TbN535TcJxzxG*loBCs!+B)2ptdhF$}`29!X0! zt0`ttYlG6?UwnF0Mi46oV{!@ZJ@A-qPBiPWJuixYO^9ud+a8}UrU|6p5SE+5RLK;J z52P0Z*L#9ZyW`Me4$h3sNGsE(*8AXA7FLSkN9$~R6KnM+r~plX=suWp&19f94pCl1 zUcdmvo$p`(_xXIVv@axasRYZcgJ3#);7MjTo-kQb_5cs%{V_?@N(;!qbRRq%c15Xc zsT<}fc?-MT5q|at{{XHkiZ_*lqpj_zT=l?_y1<~YQ!5e&ds^K-STdewk3_1eDBYCw z1RaO>?}c3yPO7!(Dh`lCZZ18nZ;B-I6s!47q;+T7=LN?SP35wOj!WE@2G{u?wmxW- zPSMoODP7v?HEKEuUA}FkA7OkfxN`{FaFKfmP%3KF&3j(L#=u+k#SZdH3p0 z{HroQ~3(XLM2!!o=D=xGa=}XHWwONo~x*;l0=Wngh~_1 z{p=vz9>n+9kUm&$tL2ncR8qr2>op|MqgRrlCW0kkTS)->o$Y;v!L~Y-@l)V~k$h3a zJ_LALhr@?2`4i0kJ?3*|`PB~yS3Q1TK0yNc)h0@q)goz1MucflRb9s59AYmkygc}H z<8K*%5S}f}d3D2Y;iHy(J;hnJS&>8}j*2>%nQ17(1z>;bQ`S1I>{$C)V_wcF1KYX4 z{*8I{JeBro-ZB=1xVMLRgNQS%=QGJEo|2L=0!2?mOlZ)@0wXeleUW!PPX7QbH$M*X zMomXg4rfW2RZP$LoiaNIE2P*k9oudGSn3nOZzjA3@i&C!=MRYw2{fD+z??0WE?u5; z8#>SGk@&|q=_2Knut={fGqH}~C=I0-QCHBx;Cq!G2RuQZZSe;jcuTE|mOMY5=J}>) z$9ew%6x7k>950f2n&>j$OrfTzju3#L++Cg9)PaHe*ui(QX}<5fKX*KgB5Pbg2dd{n z9uUjR

m#{u2(tFt{{SM!CehCRn3j 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%0DW@b(jvw;x zxc-=eTvTrX7BxqBwBF*|+xq>nT2lvC))7o;s>gD~5x3WK`eJ}$W96bUUu{3@@9m1S zit0?NgYi+-MI~0XUm=F&Y;M5&-on^pKmy89cH)&-1IJbnyJ=GP1ABXXt^Sy#=4)3@ zxm;B;)QF6eQ^OcysN^r2zyZ0kCC|uV!kQeKrz4U0k!#@2HB+>4Q_8Ctg+!iga_PBd zV(~B_+*pHyXkv;gl*?nx>ENM-9ylkbMsym~5~O}>8-RXb;2z}0v#O2cS!Qva@eMT| zTa{N$S1K5i6+%rz0!^2DbW(oUbV@48gv?Pwhfh&qVl92Y&Cve~-NmnakMZTw}z6*k;suzj~nqb1jDF*hn?hm%zu+ErLNJ+&5$db)U8c0!m$u=Z; zWx|8{x{s;Cv9bg{O2#82(ByBV_aAUa(+~8uGE_iv`ndl9XVoHVqNqgxqc9Ai$Fa4? z&e&(la!UG*8En(Ul?oM-Ne-2%1+2wb{{Rrxdto$spg2i`tdK||);H<~45leGQW>O{ zD*zKp-(So6ez+pPDy_@fSE#260?5%{P+@RNk$<;d_!b}~(x_cWPQ5H}=7JQ51BL7~ z)67ILD@i$E6d>K0n_CNwWS~hkAaKD+*zMC2z8%Zrf~I`VtkX?TM;p~LYX1PL!}6%V zTaq^W3`c1qj%oEXB&n-nEEnJTVT=m9g&Qd7A{tg!D#xR?t6%Cc6qRivNHsA)K=~2Z zrWAUbLnO^3Ng4$uEn}^%u=-)9uDH-sEliO>kb*X12qMJpFY?1TZA9GiN<5&*i7{f# zb^&fd`2pYMg&s;uZBFvjlo6Rc!}&u6Bq_IYKpSDcj;P6(#VTeLs`I-`6tII9uYRQj2vC3lk@3Qpv? zQ>vBJ$c0C${Q(D1vFriFqCB>2(kgnI8et?SRA2PjNFZ!vU%^SCsG_ksZFQ)p5{{Su}%_?5;SWlAh-Bi<5H7ylSlL{lq-%&h+Dyu#1xlEwFi#BYAZ4)AA&r*y=zTX{ zn+87kf2IEb^OaGWsZu&)MR6F`*+$p)!s|IoU>#Ff2_QCiW&Fm& z^cXzRGC7Mx?I0izyPpDYo3H_RKU`HU3`2|ZvC39vV@ zCjD>yF!4!bWgQbRL}*}W*d4YyRfhinul!-rC3!tahgX(dh2LvjkZ>$tyP27Vm4L9m z*R_eZ6^=()50+K+T@+XVMTc{McREt>eA3aZgrU`TAda6d{{YVzi{p1Ok1gblTQrpv z%{^N}r9zEu_;w*$_c~8qx4pN5MM%<`FqXl+0=3s8`L0m<*bA zkqH24>(cilpd%XIFyP%gyyNhoD58MF!I|T5mcjp`?5Gi(KF3A2PjN*yjdmGv>KV{{RsdT@rBbhU(P;G>rb; zPnl^bLASQdPum*7@Ku%=`AJupOCtGoH4g#?1QmGPuppn|DP9xL{vt++cw56P zS6NUu5V_J#?oAc1@;~2PYQw=!Y?JbiyDF9iK1D&59`_);jHFuK0YFF8eNQW(jLHtRWov`6JwHq@sD|>wUCAR?Tkn4R_Q1iFThds>Eu#JFJzmFk9(9kb04WskGA5{sIW1 zMFPc=_ha1u04z4;2_;5%TUHwIq+VFLwVzNskFmq#@g?;uf?TmS=m$ZHjmff@_lBh2 z2vV0>n6%}tqTL1X4VAxmz%d&fWG5~>FZhV&mfU;MP8A_%iW1;*fELW?5Ol8Lm@7 z7EmBZi!_F)#pXN6eMrbA1w!oB-q^D|t!K3FLGd&`^thug`l|w6q>wbeX}7E~*Wab@in@5Ql`mli&~*zMG;gSB(g_6a4e&e~6dMvh z&*{DJv5(A{ml~5|cG}m+fl5Ylgr`-D=_rpsH7IR8U#*&OwiIvobBprss`#7qK zwn|*CI*6qrX|+pc79c%_w;E-H>Iq2CrBO`e8ReRa2Y`W4*sF~98~bC&jE^2 zprX0Bwu9_`_;SsulA1b6q66@=MAZXwSvxR0bh;CZFvJMTN&=dex;PC)(FrNUzD~RB zucuYMX4q9J5@c7AqD5AcDBN1)lY5+R2g2{b%f-(;xHmJ-d5v9=_;=yy)(WhuEcy?} zS67y^Yg&4F0jFI$eNOtC_Ru=xUS2Z%EoYt(`P;|*g3tJeD&nf#jdJ;hX-iD-M_MXr zBb;cBi7TW^RDw_C`Qofv*d&z28-Z|F9jAL)xU5#1N{MDwsCAZPyDM7Tdt2KI$K_VV zHeB&X9cX40@;?4tyKk$g2G&1Z2-R}UQ7u%^1|(`K4v~9U5%=EM@{+EamU?-XFU7`^ zt4NZ6^^|Tw`k!oFlmIZRhZD(rmaOK2X=>s$l~I_&s2}1ix ziI_~|NVp)_5$gW{Ya4F`q|;HyNNCY3(9^|x1oIxiM*T7_2bakhVO8)GL0tt_~y14xg8#s!N zFD5Lv@$sf-EU6VSd!jC-7iTv7qow`u^+!)bLzEn;>*S^UJP4#JlC=-3Q4Q^XTU>V- zu5Hf8B*r#{r6r|uiel9(OMSGHp^dis?}BMznuE)go>J({?6J4xx{-Zdh`;i}^U!7) zJw%jqMKvB_6_t>%)QzMa$hf_TKYU-m4m_6UABY}0t>uR#d3^lJ16td6M8*x?$XMr?QNmt}$k7yDN-G9(*I~JB`d{1S zhpeu>DQn`Yl?pOl6ZJ(wcfoV3+ge^)TD1S zTK<^Wx$FrRI{3KGiO$+27w=Cx2>{DV)P74&b4YV)v0qO;RU9x>#Z4k=HHxq6BwuYP z0V}y+ZP?;tHhQ&*6&7{>0Lz2%jaGjNE`v(0?Cy|{$hxGHRfgi$>5F-m)8)AyXyEq)=|G!L6ui zJKo0^B=l9wQG7*}W_ewHO+aO zA}5mlWGYBYUt&TNtDx`HVnxMVd&U{+aHd_FXN#C+lu=I5Q@OK2E3nrgKgD~2YySWZ z&s;;QbyC*KwvJRL>`IU?{+;*3BC?XD`K3)QE>oA#Q9~$}SW;=7lmo9*dPR=n#2f5- z;ioPrk$H`yU`6--_rpWg8RUyoD`^2!ZNiR%_;T~g<2z5btkT5EHa6=)i% zqm8O%mP6&nrOmCiw>HE+FTinTYc!P=N^%M#8A#SLBde%!uS}c%R0ch}lZQSasuZ~% zVnCy)c7jAym8>qn08h&2^~HHV4^NTgG*o7)uDD140A8T2hn~XhH4VCg2fmYvv$XEQ zuo?hK%`D)Bnh929lT4A?!FTQKE!zgjvP!8@6iyH*R*)t4H#=YHY%d)$Rn$UdsPbfx zs%n(&eU|0DzJDxTZcK7RnqDBd^CjhXDELP*T;apsgfTE+caBxmLA-AY1d{xoIXFugDNS<4Tc=su&ZhDdb02r8L zl}$@5Mo39gA&|y;Oo77~_UuCLJ+FrDG2w0|;7%&ecsq=^cQxUDE6VDnqOZ%VU@+8D zPM(*FR6DDw>No6n1QOj#EUvTKZJ~_Js&3Z+fu_T@_}I1E#g0m&qadg1?B#Pz<2#_V zw3Mq=B(%{@DUp?4O+w6UcML_kZG3nEs(?@9n z@J4ZI0v?PZ2ITbWG1?@Vf*Bsw1;zUMh5rDaIOP8T4}wrs_^{)LsHm-hlYr~g2nFS_ zmY5QCdUS$UYh2&&j>1}snVFd-t7RnEl(EN*d(W3=6WY#H7pprY-P&KZa?$=Fn))oq zg?uwb92FUK&>Z>PNV-hQe+OVY8y~;xjZ}CVbd!NNvW`$=kd!5W(rjgRU*-sS;(r`VGpp{g0@9LC0L~ zjF)Jl1J~xce|d-7efliK2vjhT5J1wzZ-vBgtTG8So|*~z{{SOweIR3I3mWzsJC4Ht z0BjCpv}}x6ZU|HDYh%z6U{c|wxwJ%08%PhNl-q9DZ=N<4AOaOhxIZta>xGv}OD2+4 zw2OSN-w94b0cHY4TZb59GrI3(JusLCD5#Nu z<#$K$LX#_hhkq%=bJ0CX&Nzt36@}JQno4ZLs5UFH>{r}k^!!$w{{Za8=`KQNuXN|n~KFD|>a$zP-RZCet zHmtx^D0Oy#7TzW#0xfko=@XM22k^I{@K@r0A?2qZ@jYLLik#aj{{Yt+gXZ;;OG{LS z55xI#vTH?cFx)63bJF)Ln9Rc?g1p*`H#~Z2;?`5-Vf#1fv*;x7dV3^ z&ZpvzH_Y;k&n2&?^;5(6a|n@VB!Y(2>!g5gTXD8Nhlyw(Fa@OZ9eqWg#cDK@h7*2D z>-<3ZQ}ET{4qI@pZ{WX~8UFwia}ej=R&7OBo77ez%bK1>GANk)|S2%@<59t6PQl)>*Yae~_GnL7?zK{l>2G+CN7Dda)st121F$%>+(uH0yClrm zpCT#5hQsoXhW`L#d`Yt?Ony;K)L5$l_qqOGt}3;H)61-76Zo97_I6nuG%hnmmUgOk zH%Szf@`8@U0QdL45;8qRYzxXt#>%_?QEs2l4PcP68)}dO#|FZD&}>&wH|e><@5u{5 z=D$GShL?`d{{S970^{7&a0Gk}Pr{WsUQ7tC6(YVzpc1@-$^s~4*>^TO?lH`##;=7q zgE;Z+;!BD${Ju)8izlJsc{3TqC|XsUEvJeiK{p|tS$4ktZG30X_U#CcU!BpJ469Wkgwm%1~?9F0R#={D#YdqRY)rT#mx-%gv`ea?Y*s17mkA~rVJ<#zv3mQW!7{^Ylb*$Dk+GdN* zyfH9@vl6P*F_(0Eo&ds^g-HC}Wh= zOR0qV0e$w^ki-tc*rHm94KqZVqn(jel%LGOn3e~&#YMijRw!ntjci*>od<20+iR2c zIQu6OIjtmQFKROnDwitBo~h{R{{Rm?eKQ9aN|MnbJM{)Nb<^$v8{**dhn3t@&pv2y zM=AJ5qa%lj^Xj$BsH!tM!Anf8BX_*hkU|SW!uC7q9r0-@7J|Ptj+@U$uB3;^5s`hG z(g*u#EA=>Zf>|iuH%X<5(MPT#RIgi`j0{e)idNQE+Rwpr#q8+|Qt=muDdGyHhyJ{T z5O2_rCwp9exWiu)z7Kh+;TtvK9IKj@yuPih&Z(!Zqd5+H9%Q08WLV$KWL400IIuUk zx$TT^{{Yn-KweQxn`RL0b}3NntACSjcmC~x>MN^i64h0c)UMy1%YR$@VD>zlaRht6 zs;nAG%7$n8grBr>nrW)3kSy?^B{y|v1nM^GEp5J7y8i&PXe#pFA>u5av}L(b$ykB)9Pq(2?}U?miGc zI5=;@ZC5e)IxazT6P$d;<4nSaJheD-G?KDN>7tVK=@VU@e94*4otLXxz~e_UXB9JL zl(aK5%S#Dnr$B${vp8q4{{Xm)pL342zr+2&oSWdTQgdIOd`-k0Aw|tx%ZO*;+IFw4 zf;x%}s-74mWs6e=2|Uv@jz-PpMhQACid=F=w@B^n-Z6~lK8W;DlPDn4$}V)}-xgmK zoLR#epC#hU{1bAbIyei_@g{XmCUH|$sJxR+9U4w_0ijkR>U}Iv=G$bvxUS+pKyn8q zpT$=_IAeJIyvrixhQCCdXO~uJ zB=u1wBn{2>1GYX1jf!?Plm6|aqgqM$mGov(->Z}F3zQEQ{MF(9Y51Jyhco$e<02pcbwX3!)<+1J!Zv)dLHb3rsoE>RK7Qdm)HVv_i$D7;%!a1-WSd(vz&`G%=m9SismYcN|_;=Ekegjp$w#gM#rHep~1j2gss-I$-Wie z5GdBm;ZK@{%HPl^*b~%m_>ZnJo1K0gx#8i%H^}&Zo*b~^u2^Szgc4U!Q|4wz6+9)N=^9gF6oeOGZMwOVTEN@}8_qGX!OZJGbL0^eb@r)})$FqY?Qm66T}w|;RU`({NXv0>n^+z8Be}#ck1}{Otc(f@ zw94x#iLVmKKX)s{g~BO2>ny4jdK2wqf^uxv_O@S3S>%}3ND@;Vn;4w#N6T_gexnqe zNPQ~~%R+stf{mzBxMmQ^R%I&GsR;rkH?u1pj`jq0xa*9p@Ok4anO+Kb{{TDYH!Em( zN~4G~45mz$U)xlkd}5f*9PANwAq-j+1(fvK*u&9M#(i2HZCT z=J2J!+}Y#42JuP4T(rz`4k)0cOshHKjINrtlP0Z#SsTiComfE}=}~Voz-x&^5vUM6 zLQo)aE#Hn_X|Oil05r3^!zYTr8{ZVn!;AQLD)BwS9ujFdN|KtkNw|M5b(1`5sbz~x zv8V>o{urH_!^|6A#~liIX64s3xl76@I9r>X@y)zQaddSxH6uQ#ppKSCf%NF6P#wI$ zmU}z4qprrl3}8oyPlZQ<{{R)083!5i_cWs9-fK@!BGsnVd` zi!mgea~?4~GejE)vTy3`A3wo;cMWT!ckd1Q+T%y!pT^nmFg$bf(~7h1T=5Sovk7bI zqD+@Ii6gC!7-=DeC!J8TYndWhZmh#guIAUqzhm;W7Lw7H1bS|7Ya4xfV`P67Zx9>- z;!DOyFgc6LdXL&18x1C3l2T@?7(~qlECx26LG=`Nb_z%YswwD3HRnS>C4zZphI#40 z^+^}2Py6@!TOB`yvBONpxKW{xEH9GR$_&md$g;hu8GSBUu0tz@F@=j!zn)mCi+k9X z{X5~~I27_N9MtO*Q#jQgg|@_Az})n{lfPUu)czeHrAnzI6%tO8K@5slUV>~|-7m1; zYuf(+DQ6LJ9e#ZtTloC5DW;VGVJ$Th)4YP(G_X(%JSZxg${#NkT;TX4E!z1M;5ZeZ7VrgmCF9 zLZX%%j;6qLJq_=RG)`4r-4fDyO0go3G??y4ACTX;?Ti!g?@?0+EApB;XiU)5Ra8ec zr7NImi_}zpYZAL3d}mtEr_TJbfGnW*KQa2_20VAeGxFPqqtb#O#MM=@nFYvLqg&Y8 z_Seu}_xWR2#pAeK-m7!LMQT{;Sug$_(=`4l`LhH|PbnM+QtaWZ75@MiNVngv#0%rG zT`vdjMP6R|cDa$S{SG+_{{RmSK4F)5i|0E+)FB4|0V@~$`s?X-9Y;Z8PWQIMe0Ae& zxbD=np}YD4$BX;OiLT-&cRCBz9g=&7jCz&J@A!(T(RdrfOZlvkijE;R2F`629j)@c ziTYzu{sosbi%lt)oy4G+Phlr_YCd=fG zr-)nz0EShHkyv}!hyMV^H4Wfus-k`h;yOKHVo73hgY#>54*s)Rs+G>Pj84 z-&?d5!>kMyM8+*Us8;Sl>42F_umb+T6W70Awh5VI2&}h}k73{IgyE4?xN_Q9fVb>@ z@K>B7Jd{U?a@Wiurkpg1Q46U@we%2r{{YS;nSNl|#Voa~p=%aKj$|IC)u@8Vd#SbW zie!*k#9)h`Nxkj%#9Fv!IZ#Ths$`}C!#V}o$Ey0iUZPL@VuY5*VM_>br6G20YU-#K z*1ubWw@>e;Du!JQ%vqOhk4yZp#ZSakRYDKMDrI#gw7Rjnleb30vdf_voi#ZmuJ;4m zd_2ksLdFsGkpfkXPnb@t->tu%5qXwHA~U3(tU6#xrIJ95gs~R`1J6>l@VA>P(=D&8 zn+ta*0LheWD9PoGm?>1$E;bh4{k~YY{9~TAEiAb;3&z>CQZfYUQ5#~`_cz-KR&j(f zNOHW5WzB2K7S;ukYsOpN$!)^8(1Bp7D%^}pJY4_-HPSoJUk*IApCimL-q*^o#8Ju4C{{Y4<>DfY( z9P2q>8?!lGEH@;D-0g%J!50@&yYFrOSSZSj&7w66VR72{425|1VyrLU4S4cNdxu2# znP!yvr!Jd@n=TU8L7CKM0;y~nQd&fXq96AD>0ji-=Z2bUh0PKcRE`RW0d`2z^U~4O>H2MY<xjS?_TL?p#Qr5IhJnJ1)s?M;n^$-aby{&Vn z1XNmAd!(?=NG9i{hf5BJt|l_9i0hJF>ttCq$K@k=mjghu>@REIZle^euOVa&9D18k z(f|bg1`*RPtzK|p?X~gr#4XW_?`t)^`{2xi@~cS^8BSFcvqcVBR7zTM-~}L+b!{XO z*zOO|j5)!a#Y0GBu5A>hmgsHkU~UD8-1Wq6Y}N`uwDl7_vdBP+CEes}5wQJm$2B!h ze^P>_5%RQlF~$XoDHb}t`y47+0l-g=D#|y9;GG{bsjH`w8p)^pOuDbA2f0wky|oRn z?>hw&7GQ3=hwG2En4oHQnc36}IO@c7z5auI0P{^MvglB3YyjAf_$crzs$7n;mh&Nn zR3m~|s(Tv~Zryr}I+RHYkVsuSSR6#-o#dQC7RW7YjmP|AO-k$)m_5KGA93=&A)&~y z6*-L@GtpH?H7s=yx;hfV=FB<^_ZHizz93vLJgWs~4OXd2+6g?RO*SnV8ij|*GY`{z zT*#z~RCsD%(Xj^oacuabhv!_vpFYWIB^jbjSri{jEv>!!^dN)S;V*97gy`kP6*iuI z6%_#;WC4g@NdTK$ZqD8}Gfh7>DK6?NLie`NmvmtLiBH z*wN3VY8yH?LIDgd+rIdjP{Nh!u!$Nd6_1+01Ec|eNF;Ca#jQMol2P(!)%7)UJPG7$ zW^1Y30y`7G^Y_H3g!r~Rk1@-$J|oGSj5362BdE*ftC|&+85u))k+5ZTBrrGX1})lV z6!1!|Or*vIn^3jKwZBX|e$t|9QeqLiD+DnU`LBJ?()eTFy9EOQwIBhG8M zb0qzdkyT6QQqdWVf{Nimj7r42s34t8Zgp>kIJ+#R$SdpP6}en(L0Bl-3U@5hJaM6E zm93{ku^zHt-E~i-90$W9vrBCCMi_Bv&!qI zQ`lGy{=5E|uJKq1w)v-Qu*)PfSJX!XR0jo9_=H#3e2-i)PGxDNs3q4^F&lKml6pp^ zrAkUiB^(1Q+yd`y?mm0}04z1u02&D5Ag-H$yZwKi&N47UO@f6-jiOUKGO_h^-ycXc zEXb+|EKT(RVeg8>a=J)abbvs;h0jbZD4ta!M`;)zK(XBS1b&!s2GJX&rAon?WvchYJ4bER=2uRtyOzZIA1PqnGfpR0yJdQnKif3vFUF{SEK-!vbb*XmV(sqK;;zN`;Jo znwmr!-BS0yq;9_5H^KB-gqm4qCR3#PPTfVWea*2fcsU9s6sCDE8*wI61w0u?5a$_2 zkl+exnIZ}pcF@BQ)tp0|ac`L=es`SJ1SOzKnu#aU2^TkVcL06ui(3?m?h-VR+*ybn z2fuq__GP&}EHo7UMMXE`7V8|5KH!02AxqzIZ@<0qWWNfrCaFP%4SA`5HkzWcQb|5n z?=_nfdyb!${{SuVBgr#Z7LCkWP(oCyxC6^15=ndSau}bM{{SpY=FBpF9?GFY)YVnG zS)KLhQo!!=b_DNxp184P{IOELxczK|aS% zM?p@EX_QD@-E?lFt@?jV7_lUT2(&{r%K)Rdx7Tb^l4~#uhtaSeUguUER5Iw*1W~Gw zQz#qu>({;wvK~smGLY5*j$6h_I$qmYcemgDF@c^tS%|AogM3Z1wUPl2GBjAh2*YE$#C-!4Dnzg9JNaPS z*kh~Jtjttc{@5q}%B>6k0O*6ZJWt*){{Xaq+45ef?10^)1g=s)#4_2Gd)c{M{SQojmv+Co{FYk zT=;K|7D?@0pRrJP+MbhtpHcmsX{W(G1kq&NTE*I;i}y^2U!*%bYZmNm7k=Yz*zCQ_ zwZlaj9=|ord(QgrBhhC8bdX33kz;ZI>4dfGS41EW$^rK6ip*YAfyfJTZau#EN<|0( z7t*HJ8+FHfEH`V1O3tgr0S1Al#BH^=z*8ZXEhu9~2VJk!eXvB5UrK_@Z_R%A6_})# zAh`pl%lqwyhhqyH$tL6g70rYDj zNbW&WTdl$N>~Tsam30bObm{cRj5Np!n=^c`irY}S+}h-A->3Uv$u^SmPb7?rVQ@y; ziMY2+e7?O=mAe6QPf>-RK{^T4LHFr^rDuv!BzhfmZ{FRv`C?qt%|jWSuNjdWOAC|M z$NAx8s4CjZf`@%1_P!hCR*4nZwb%jlH~#=^eH4JJD0>n`f$i^X1Fn^qH_0uXWtla2 zpr0+u{{RgtQ^gHJmOsCdSeBCaxYckz!wzDR#zl~|6Ee*sB|T=c58>opK}j8bVehN9 zk}%M-NEi^t=U_VzrVNguqw?-7_X;*P_reQ2lcRVX(>ms+imtXQ>T1fWNXmwqB-s!B z-z`Kf@CX@UWFjKFUC}FIYKrG!^c01c`{&)`v`KWx& zB}QoSFD|lN)uojxGzjBhz!17fKg+*dJI0Ag5Ggg0Y=HG9<85C1VZNg=@}p5GWL-gs z>2BA znWS2HqmCi~AdBDU{KgiiF__*>EL63L?7vJkvVv^_dy-gU0hUBFje~c!@JutP151D! z%x*r|W{J?TH+=vRU^m|m(2*h(3FWno?!9-zUiTE4Glb;f9N1|Mdz%|!8R9OYDG~J9 zkLDnco$*yQI!Gqe#IPTkm=1^A^uvRsfI_aUK>%Ef?Sb2PL$tJEG3QXvoMl-~KxSAe zXr!omZ{2|^8J%6jI6kGiiw@SqR$Kd8fI8M@6*ZAIp%SrDJtoDqb+x-VaKDE?lE&n?>wUKR;ctxp0F^!`<0=ym5YbOkf$6GgX^99V zk#4`3UiRr>bMvvotQ8s7W180GxkP4KVJi7eBvyAU%8GQKkr(#Ez=_edQ^FW2ENq0E z?{WO?gH~#mnl@OZSwY?6Q*-jZ6&w%U?G#Rw4u~K9H&nt*$1*Zml!H!I-dk$?tPjXv zZ*hrh)WZ+#>rzvR5(6BPCt1zAQG85Tm! zgsA~K54e%! zO&M&I^9glA8dVBMktU`FHYcgr8}#*juui42G6Sl?y7nFL)`QheuWAt_RfvTVp*AXZ z2j~3o-t^?L1%Xb4FuvbBF0w5~zb#hdYbm+k++k&CqDYm?5O#eal1;y+*jvY%z*H|h z;iz+UGDGDhShtqIX+EBdarHa@0Ja;TIj&Cu%c_v(Ot72OOzcUr9VkfOdjWr#>xrFY zW}ay&WV}1-j1zLYfFpkUTj+jx^=lntWPN*(#1XMJ0Fm~_2rOY)WVSMzQ#x#-da7Dj zDkX|Il6r=XfMgm0A%lMq)NTj$7b?H}UjG0r5SfIrmxh?VGB9KXO|>n$AD2vHV?9#$3ro<$ozIrl z<=jUmUT7*BC)4ExkqFd%EG$&|h$8kob+#VqlAfLz;LGXM7W7`^89v`$_>ZKoQ&Ahs zGcu_RR02!y{qKV!eaPP;$0do!AU7{`Dvw&d6{FFHNpY1@9po2JTf9h zI)fya8jnv=9c_kcDW0ZiC3RDw)_c&`_8--R!T79KH zU0hn{k~$QrMC6)wD99{Nq>u@=z-{-yF;nV|BGB+LAh;Jc-?+ZV ze!o09B1l$1-b*OE>T*LkJT}LZrd{eFJsrXGtw7UXjth`t`}F!ZO`g)uP+~wRZGKs7nnokidf^S zrIAB|!S%-_^!2s7<5|UAOhhfe0vD-j*%$bCpv>ub*Tl0@!A7&DSCmrD@)L5uiDRWo z_6@zxI;ivW-M@8CyL2a}Icxs_4nb<{=fyT@HAsR&hv#{!^}henDJ+L_~Pspor-<*@d~=l=l2A74?La{I%r9addaO`@lW zx6X}K_C_v+*lFN{{X%gX8qblB9S5A+rRu`nGu2#OJCUk0H!IRXd^{~LRI;nfvm=2vSw_Hyp4Z1=A z517c-x8DibrB)U;8~SlpsN+$E8X~s_M5td}jLzjc6$%%$k(xb@{H} z`NBg;)=`Grl13D8-e2V)w^MJP{{U z5DB>hwXyV@q^TXnuVBM_;6!UR&ZRc7H{bi)2OOBnTUkXK8tZmD8=cR8?)dQ98B7tV+?d0xh@880RMJK#0h7WFj^ITH^lzd{*v5GcW{>rrrMlvxVA7 z(CPCOl6Dr|NB3+Fs;WYRaekffwzw1y9!W5(bEyTJpw+PZ;Te@gk_Z7{eInqC+kf=J z?-!ClZN<*k>x!-dDFWxGy|IL)wWR?yJ2*rPLoKWc{&=Ejnc6r8mT`T@zsm>tWGjYi zw_|Ph>w&zsM%AsQBIf@9KYU?nAz5KUpqdA|g3WQN{r;HwqB0hbSVjb1=Wl=04yGMx z<}xdSKc*=1P^vQkO@a%afS#WHu@7LZpe`$6eiPvf;G5!WS0Zaz@(uunZZE3*PR(!s z0C3}6lgv!29xY+UyYvA2kJA~Q${u!b*Dt&_c&_CRVM|>6O8^-`=Dx?&ydrX`p-^Cl z_I7VAROvArt>chs>v9OjB2-d5>lX7@ioo+wGYpE?VLP%aJkf0+4UY2Kn|WRfjK7@-<}H`lQ1gkXiW z!KpN$1gSd$J-*=LuxC_3xU_vFY+OkkiV5m1+W3-C-Am3^>uo3NhB_FONa?C1h**Jr z#rHUWftX9R#B3}!*kbG=!mdSfTW9z+a-V=X%i~8a;a+9%2MqH!hEs&NhcIlXHl&WC zl6m8T5f7M-3W6F#Vn)Q@wl^!!KL-4R%qn~qaThbZ9&&@i{{S@ej(6nzFIB=>7Gq6c zO~o8NB1qE;l&8}hpemR2l7Lv9GU>-Veg`~Ow}Y;9RP%8-N`5kVcxyW0;Y}4^;hha+ z3aK)=2l6~f*6Ky=W4;-ADdLlid2i3&NOP-<>-eXc?ZNr}Uz{x+er+SmQxp$&ia91O zBiHipVsC6}HC#G*CUe;O01EXv^`Xpj1zw9&6Iug>oBWqb9x^-}avv!0%j0K?c%#7Q zCcHgm+#|!)HQWcroHLojHes7oMJpvamYM(>1%KR@jzY_6h&!#s&oS_8;r{@Gxhu;q zB*^|99vnHdlz;8kQ=R8I<#!Upl;#Gk<>Fb}$at8@-j6fP)(f){Yl3m13O|TueN$88 z(u0XIo+!^aTb&seZvfkWf6IiKFY&cYvMiN$G~@o?ji8i#C&H{;GUnvzZt{LJ}Ke!i->rHWEqZI zlhRZesr>%{Hbjie9)TOg0BvsM{!@%g@cZ#h@Yl;e1LPe1%<$30{7cTBU1dp=WO?rm zaRcQr=2Xx-8f463jzn4P4cJPuuB}85SzI{s&*FXIkBE6s#ry^0hr{O`a}K{V<}VTR z20z#t`{mU1Q|2VF`*>RASAafe_`m0eg+63>5X-VYC#22u%*K#Q#PZca!?aWsRBHKs;Gg$|&G?A} zsU!EjeKrxF3H*rgE#m(GnVumy+m*f;_eiP*;cgAl;O`Fz8)BZOyYK3=^ zfYS_0wW%fYs5#5P7O5 zcGf)TrI3>B)_Yvr2l!F(KjEjtwoA=kP56S~3Ax|EoIzKY=ed6q@O4{IX1OhF5t!{u zQcN?Vn=QgR*@Ij-b8EVd4C8Z{U69)Lk306UyUM!x(X_Tn9RPXR{+&JQ9q}~ee=WHm z&fXWwxp~Q6V)6=uG2zO5!!zMr{k-_{>fzCDuBwC7ZLXhFu2DtS8QLLRHk^9Ed zI;jHvdS4qK_=Wh;;LjEOU&=(~?+EcP4D#QDIA~-!D(Bgo*XDJRnKiW4bqwy$Au7AG zGkR`GEOD+F(kY#s$s)DR*1hqw&w69DinIEN>hnCuGJ=viNGEw^N?4Q2N_KKsA|=k0P;3_a00(S8 z#Wt!q6#>&x=DhmMj6Zfj>@C-(*h)zdNg@|?1e={U)_eY!!Bn*MX-Otw<+-3jDdm)O ziJToEpL1hxr_Ub6Ni5E-GQ3d^idO8)Z{>$baIu96QATEr$R}n7!C1D$Tfgawq+OQV zuo`cBYr?N2P`U&%G-~0MO@^<1@S8}IE7&mW>L=fOTkC;<`J-9y2L$lyd@=K`I&L4y zTZ}*V)|V?x)#*^xwGrWf=A9+Bp%<9!|;DnG58(6 z8}RbIIEyZRV7EHv&*aJ$L->Wu*M}je6(udSZ7!q-xl%hEU}<}(Xq*PqYyA5h1S~$$ zK4lY;4AU791rWHoxEHn_JnEXr#XprKh;cRF zI;#1AZ?^rv+Yj4|L0PnBQ<=#}Fr}!DNTNI4me#*pe2ylR^^wX}I#w#gpG~X)_WEI@ zOedBy!U-IJ8cjR&>+<)*gmHtaT76e=S9|Vu>GiS2a@;5*qL4(|lt7o0%SLkJvlHC@ zxILyvSl{=6ivgzBW%fVM5$b((@yfPSecIg**XxJ;t1xpMFuFjmVoCDF?{2p{_rs!T zr4BR_&!ojQmd@phfH$><$JpasUOQ5n5y8}vPdZIDUr>^UU=#+aPQ8W7V`Me8QahOc z0C=`*fqM>s9lQSk&NaE?{qp$a<^KSfq4d)@9^VgnT%9^D&(T8hMffYGE*s)0 z8Ic&cK3OD@X&iz@?cIg`Up#KdMReOMv!{+w%1-+(1(nfR9EBZveLqu=Tp$Fv)>Pl?j_SsR$0-C@fKBxQxVKyf zEz4>ll;7X33!MoqYum2g_rR{s3f!*3_UXPLgVhKI&}xTVip!)BHn&ggVLKFP)xYSm z00Y?Dt_YFM$WTjxxb2Ah)ytWRxM)lzqtW}rxZIFO^4O1mrV%MjV{E0WvxsQRB*-Qj z!BrQz7uz0X)zj5R-fR^KW+&I&b{O_Njyh&ZmI5RM0LS*2)Bg^y8fiT5~3 z+)6UxX|`#qq?P{$866{{WT;tDrp6nx+UG2T9#Jsp)V#_QRQ! zMP?RP{{Stz{{VK!$YW!sNY%F{#e4nmeh~pfjq*rRR8m$hs#=AV*dIpZ1Kf|k6@;{M zGdb!2ARU|A5$w+nwyDw81JN%lMS!ns!y(`QpvK=h`AFo1=gH$RpB zUn6jS_?EnkIT2Dl65=vC+Ck6A5&_PRQ%0~pJR$c%C4f?TXHtSu3kt|Mq9PU z5*Qw$`^?Ct?91l|Ak-tVoY=MY1VCjHu$ba!f8EmDEOJOdxwyabBLJ;sFP$AcsA-l&aFS_e48d4| zx4BR++W4z4%c>>Iqo&LxmD$O8AiwUlTv&nfAI}f9v@_7fO9_B1OuB}R?X~***|)+& zOOoFDDm4{j6ppA-)Cift(i3zfT=(f=zt0x}ICv_ihlS;)%ntb#F3Q^d!XCmKPl? z1--E2OHV^AleBO6cb9f6x~pz)Z+}t2QqvJ5((0rV#ZM&mG6Llm-liP^JDYo8n_y8* z$3*~|oy$usOv>8BFdZ$>pY_6U#TYQ8gIa-YyY03mRS<}#e>xXO3#EYsX*cO?4;=_p z3{(}qqHVp-9LT~0A*w>t)1*+OWlInR*p2@H=LPBXhSqJ^e|@mCLRK~xZ&GB&KCoPbz>yGcS$?YSmg4`4>8V=PWSYUTE1jj_>faUM@=`IO-D$Q z9m9mXFWmnCTvhR2L8wk3mbq~e6jSIjaiaX^8?o5k6&?ureyLeW2&W(&wVFL$8B~j zr(@9KS{@T#_R{sEsDQFGLQV8Cx{;vRn;*5#8)frmbXl3SfC`Uck1C;(qM+5J@>A8! z!^{lCq=W%$fzsGAm{n%YJQVa(MO7Sk347>O1d>|9{rY=iTPv?AF9NWWj!J5Hq!m!j zDbuDuEyCDuu|3Eq`s2z86#{wc(S-!+AFc2k!!&ZRc2b1;0NjD@f1cPjo&fr+Lf8N{ z>+gIJX((HLRLh3=tnij)PoCvz8Ld=!A~Qo3L}6W8HzgztH3f5|+Uj=}HX^*zz5_)@ z(lk>^G1R90S8HD0!2bX&Lgp&Uu{c|5X0RPEy@&F}QPZJSEh$G0Z;&0Z#>S;RO`5pM z;iih2DUl>+a2%D9i0W_Gp|I`u$JLxgS2HS7Xn{(A;xq!*9{q2&=L|J+lq(5kR5kz| z^&BCXW;td>L@O(5V~%Ci0KV;OcKhI^b6PB^4Zcaz9R!h8J3xlPZ5d*Ig9O*ES(i-| zb(M`u9t5e3%VaGXO+w)JJ6hd;mLl1GcMwifGL}rPmYv7$8$mOyeL(>FP`2jg=GMKh zi;0zR=55CHGk(mU{H#D0+v{vJR8N!nvQG_M2#)2E44bNx`E72aar40`FX5`= zO0eq^FjqtXw0mv`YmfA|&ks^dlh)+4(^TbUEm~bNSFxJ z5wf1Z`*k+K7Y>RX+6q=n!7Bn1Vd)IWE*}2??R*P9S5f$;hP7v^ zF)IppjfKd$BdmunSPDxCGb_ zr`sCc@%JS+o5FBOG!;;_2&na`220ek6}_%MA+YKC-y110jWr7{@v?$%u_pHbkLoe5 z{{S2G^;2j3v^hgVTbjd8vD2uCU6@qKCXfjA9a=@ZcI#|vIHOCMwQe{o0Gt)Kukh^A zR{sF#zZ6w8v(`@}na)Q{%BU{Zf~kg}e<-tC9WZ_ihVt;VRk7zY)y4wI(X>T%TW~iW zI(@Ou&-iyUEX_Gr;Q4FLIWJ$u2Vyx1-k~>?`(;J@u01%Z_k??HV)WXCwqbnY+eAWbzI$vvjK3MJj)QizZPfJ{%ybyd@KE;}4m@th;nI~X- z;W?F+!6VBgUc(BA2zvrUDYeJ9xAVuOqZda|)*$-2-yO0w$4YGsOoqh1*R}ABpsbqh zWDB>o{&*@vx}-%q-L6T!x}NwBRUj?Fa(|V-v4<0cECd{;OwwT`FsG%Q49%oi!YSwp z+@H1g!I^z5IdwY08b+^uQaD}RuhjhT(UZa|IIlUV^?&gpQKrJdm=!zw*n^2Ap}f{7 zMy;*@w`@^lf#(U&HH3t+fFzN&7U({w`Qg3Q9hKOZTY$Iue}Bsl)EP!)oYzuixlI*T zWnEJ16g1FA(n~wBuvCpfW@2^#0!hZwxVPaW&dybMHRJCV9O$X1;40j?vewHuMo7e! z&rdyEaJ;pS4wxJXRIDRY4fT=vM9Zj-IuA8whpAB5$rd^-L>u{vTmYisY&Ik1g%?tm zEwY~d)a}z1$qb0bC5>*T*CVIP`r#+kBme*``hhrMbrc}dCF45~#BMBl_3w*&#`#Qi z&{XkNDokr2K$3`wQzBdoxBmcdTl-vM;;Ts~m{5?aH|x^~7mq_lGKmn2GLknP4i`HK zZG`CGl*^S@$C*&mR8vY_fC^k~bMJA97>-FIg?28+*S}A$EpH4|#YLOuoIMk&{u*~e zmOCk8QpEN2{{T!}$i|kCum^AfzWs1oNp}hpiI>01xXdwuX?X4LelOC@Ap zZfj2)B1b6I9f3lj$9=rp{{Z+uOgQG*rw>yl4QC0-ndJ4c(n2SOXY)f<^S~ z#X;O^Be28}pEjjsSYBG0B)^w(Zcq1oJ%Es^IORN2<`p!+q*|ka>Hh!^Czo~eR^;#U zy8~}>^2UpsycL)5KLqeSOwPGX z{7qjqB$>ok8mcLyNMt6TSENX69D-CZ8jMHAufprZ7lKX-$T^qI9MhK>uMB3n$jNDc zVrElR%^gcq$v6@$kjG@x1cOi{-rHiZ*XhgrAo07(@~sUk_U<6k*0pT1)|ZjIu*#t< zg2Lku87($g+(VLPvKExn$RpJ3R`I>m+zz%3O}@R3BFig;bEp<3-K+`QrXFEhDZgn{ zH1bf?h}EEsA!y}d${BC`BHEZAmAl^uGb|M_x{V=CO6DR;kvww;m8C{jB)XPsH@@Xh zUF>mCoUtKAz_7XZ`r(3#IOuZ>&n*TR>47r9OM01H-rMhC>isb99Yxwm84km3x|~Lt z)F~Xz&7z$cGX~Uq5_{nY%CfvgQUxG%u+g$P*#cX4BvJt?n#wPGyVbJw$t%pb|F2&?7KnlC>s4alMzQAIepSkIjLY`Og23?qBTpN(m@Sa6O zS(n8)s;`AftIegBKtoEz^h8udL9+UfRyc0Wsp)ARt}iG=Jt!?}q>9>PRv#~Z=X_H~ zmgQfw+EG<38LH}-y~mJ|DwCv(T)PsWTVeX!Fnk?&Am;auPGNB`1ahvUgfiUAD9VO+ zm{n)hQqw@Nnbs9RV~$2=XJgx@U}>M>_Zh_|wVq+|M|dIq?4gJQTFj)UU#r$=@Lj?n8zzaBe05baHhw5AC|!Vaed$_)JG(o zY#c0tK;=!GcT?N?Vp*4EnGJ4HRaIBUGgPaNY2s&8LjJ>13w`>6df}j-TO$AsuWsjT6D*@4eI%k$6ftTK zbzpD5&i>dv;g&r#-@7`KQtCIbCg74gcfgP{MjF~kV0Bn-Fr`b0VpV30>9_)iSEK*gujy42oVTEQN~p+6u^&AR>ZJK#QE zaknt@tgD1L7l$~Di@3u#nW(68ysieQsI6eS$|Om<8v;lozzf`CVi`@fS)()*P=)i| zsx-M#W2A#?ZMGb<8I4@fv$$9m1xOdusUu5;SFjg09eSR)+ZIRgR``l>c2z~1=A5SC z+=Emg!xnGFS$!=+p#X(=kiL`J#N2OtV$*Za;bG%vkXapf7xAYgb4soYp@7uZ=J_pk zK4niy60WCtRu?iNt&gda-8UH54kxC2wl+Xdm4$8EIXRY}g4d;*j#_avUbPDTS#Qj& z17B{N5N(5Co_felGRqY_jTneZW7Vxr=Kla+mg3#;1dA<1k~=BTpaR4IEp4sXn*+DD zE2cUxGD^s?+emKY?Xdg*04!T{Ud;r6+E0~~HI&aSEoCb~nLvEEO-euj4uwfmU{|5< z^}~i#w35iNMNVX&%GfcmSN9{h1Gl~!q>_1Rqo}H@{{Z91Nuo7kE}EN5FtF@xx$Ap% z!qgJ26;xFVDMq^uDQn)w-Fsl6WelKrS2~K4Kf(%lrH$)UXp%z0?r-n!wk7e=)oBK; zV*!e?o7^9#dw;eeIZXr1>E+2Q)D&4776CyQ{KbynY)@#alA&gb8Q@r&Z4AeK7CQ@e z>xZ?3@>R$k6%$iIE#pZMJl$6^*p0WaJ6q+AYIy0SnwyQed?u1AI%Udj84;Hy(n*P7 z?0rl0*!yE;Eh7ryB{X$LC5-Egx94MF>Fr`b-x|~L@tDsyF*p{T>IFqTE>#l9iRnmW zW}Mx2zo@9a{{YG@YvP8uP|DnJR|7D$yl?RE*HBb)OT?CEn#zW;_^&Si0Oe0HCBOJ{ zp1(8J{YAa8(VSVI2?*29&3Ij;BIL%x;nb{xhr^GE7oRJE#QbHKXlDw+ zh@h7C7AIiVJvS#E3P_nW&SaA*pe#TK_aO8Z$B%n+2pm#T>-aBF_G12q%3RWah<}D_ zcyf=BIW}U{?>MC56AXpMf=f_px&Htzo9*wU<3?T%V|3yEDRV4u6L~=t9fhWlZhrU1 z=zc%hj(x;gUx&FGukn?OmhmIT99)|{06wGBVs`IgjV|~rQBT4d<9SjmJMF1`B&@79 z{aWMcj@#X<8tn{Ej{`q7$$NZDWso05nT1h-0b1Q|Ff&G^pf?PsW7huwTpraLW+jv? zYzJ+W;krUqo$iF+s3)(zhszy#oR=jCDNWssZ)R@&ZG>T-2u*Q>7v; zJdbl6fmkzM=h98j>yMlVsX{e*M1ULHrvCsv@f^w}r=a4T+a(IIB}^tnd-|P*;Sad( zJ%}T|B{_9G)lASvl1l3ol9dB}Dm5Ryfj_Pjr;G;DYgS@l;B zWE1D+pEIBFjYS`xANH+YljarF2mlM;wj`ezi6b8l-hRgF5nJ{$TekV7G28UV9-N8z zf%vfS@sx1?00wfao4iMm@Sast(oy9eTr*MYXIaA{Y z;p5HDTXAI&;13WBE=*?0<0a`cl#4Neq@IRT*aR%lzo|z;!+d;BqqDk(>shD=b9V#o z7xG)!_3;P{WKpk*)W3kg4Bj1lO!E_u_*b9Y`j?SeR$rAznB|pAB`jkym+=BQBQH~R z1yPlN8=I5RV`=exBt9GxJI0?86p-AM2Dc=-_3v%*%}k`Un%zSwH?aWUd)nAGmPqFn zvR2NqG;#juc}Zy-Pz6c0+ZG`Ei+9J_&!&6bxw01fgMScD-oAV~x-Fpi{_t(#%fi+} z%WT__9wz9y=lgQ9x`Q@=O+@dOBvHpAN&f)F=&V_k>Khdn>P9tm4qCK%gfdf4CSv9j z1ghScKrQA1KZ{UhvFumpkEW3sJgt?$xUzsP+ols|jiiWFO=ueAga8%4*X#cPj5W=4 zanqe=&mV;a40W3d%)pAA)X!owuvdnTLt$`^W47O?^Tpaxs1;$L+paCnMk#X+BhE9( z$XRBZSQuL3GZcXogY3vJ`r_jf9a&ru2?GBB*A?_#N-a$f6aeiDVsOPHlDP~zbv2v?mS^i-_ z1dn0z!|r1|lS+t7k1b4KH$@k|-rJLk5Ib=ot5RTCOH+XGB(bweBQagaLM#Qo_}|yU zH{m-si79e_5*{G(_J_m#6%2B0mB|uutkJngGWSfqT^UWR(=xJ)AY$D9QB{5xL}vkX z$gZ~+)@CIua{DVT^?yz^s@t^B^pPl?P5Q~AhmP&PUPsNN0vd%7^Tt>uq-mF z!Y^;HeX%y>C&v%MUo?5Gz+9?>m;A`!toJ<5>9R;Gb6Q$RX=tUHh*z3HC#6GL{{a2N z8D-;Z$B!X=FLJ*s;tn)1a|bWaDr&N5sd8$XTBn9jz|AhH5WnOhN?dngj(r}MZ9b|Z zAs~-lerEYEq?=O{;c(rL_+Ors%jP+E3J>Y1`~CXjh|sDVSV?WZe=IFgI?Ft=)1*+v zvMMdgs2dAk=rKW(F&UIyoDIf0qs|w|2W3X9VlTw>vKG^-juem+zx`JmeXWdz@c#hF z{O`m^HFCaIlGbWd`Qme!cLBSY2c%>IN-s;l2-C=T*}O zi0=flfOP8r0N3mRW6?+d037`K;{<$5_;BK{3%q%ia32`)e=E4pF|5kt&7!N}JnUw4 zX&XxDCX*{&NOT(r$r!6$-u1W)_fY%o7Yp(wQOiQU^BOq*}yS{+NVuI<+N5 zCU<#RsopkXpOg(i6K{KBcN08dhdP*T-+!JF7$M5>ZY-x5q?(}_6@Tcmk_&p6lVHGg zJwW+&$57wl?czRF^8WyZJWFxMA9D|aI6pnDtjTg}RLyfJX{P)%P|r}(FPKH+GSsTv zZK^Uc%k4GEicrI#R${lXCgS7ylxT=E|k0OouSb^6Gl5=9QshKLcG(h6x?fy&;uD+-Y?-xmnW3Bp{yr{*3* z4okxMWO-&o!*uz=<~g=x(S~)7!Ha8lELum>i*j}V417P*Hf(N;7dy$!Z_Eq({?)!@ zd#uc8dK3At&&M&1*1lzuj8LRX(D_2+%PK5EzWS~=zW3{f%DT6$s`H*gThbQMs#pb8 z9+leUF8=3p*ApIK@eJHq#(Y`D(!(7cMr)c@=5o^@vc&UF^0F_;8Au)W-w_r?a*T!b z0u6xn$5C!uo@?bDB|3sKuQ;xbrkgKEoYK@&Iy`G30kpc63_1~Wz5RwSk03lYb4$ec z8)iHS%4!}OuHs5ewewk{%`?heu?;%O9Au=G465y_RP>GQbI=@EEW&BiFw2EZAym>V zfQx#Sq$c<6(Bbl$vX+LV=2Q-85I%!X=6>;`De7Ha)bzhmwha=V)xKS_}BgcPt=$pt=R1#D&s zl(cNKKSVJ|{G&H)KRosuwYuF2H4YAed_;z_Y!p*^a z_wfUmW%+(##)meh;W`SYiqcThB_wrosuR=Al6XTA)Iy-_EsjYeok9fA0RXgzaLh0L zcNpo5;2GmjmVB<8nLZo&pTxOW1^(a6DRa&ouCI_o1x09w@bl8iGkPOtNa@}^L~1J{ z-uiD#w4zt&Uf8dv!t$?hg2v9$?n`xkAvkm5dCXpAaRmp5o;c)3AUQ#ox>M!V*|blY zW_(0^wJ$rOLn6~ht(jFW8p(6iV%&2FkA5rMk>#K5TK#qnRw_U6Y2_@>VI7bU67sVK%xQXgELpCklFjO|u+F|)<=j2s>%%_^WIW~PWp5E=+$WV3%(%aa<`GR;72ZO` zGcz3_gmIu}eJG1|ZO=Gnsy0T(wXJ)TD9_JEC1Kz(pem&2r_@jvUina`v zi-)q>jKZq2mV%XZ!-2i90s3WD0*VulTkmZ#X8D?eW)k9MiMAIjjt^$!8+Qb2I*8On7!&NcU z)`hGg=}MABg7GsA!2oO;<70mKp4L;+*5yH@h{ZDg^;uMcZrwloH@&`JJX>w05nR;4 zD(VA3qBJ5jF>ac)dat>?y0JF3x}0m1#wKf$H!`?dmo%rIhbyYdA^c5CCZj~ry+Xw- zYu5K~P&+W&*yChyv%D1IXnju@P#bdHE^qFC;~K;9v60uu%#60Ks+OtpDKg4xYDx8J zU2!YRBw+ih$ri6--OaH}h_=8BalwmxYAb$!;p~Pud^B^ms-muCuA7Z%cf<^Ina z3fNxefd2r){ZC&08M(-5=_o2_pyQb0P-JpIe5w{Y z2s_-je{+rUMk_P{6lx(KSWRWlMEPfp}D$+;%q`M_CjW0mK$=BF&2OAzY~ z?9uyzJCS~)Y#I206jgLZBC%m5$n_~uZEtOu;~O|jbVUm!v4q@$$}hItV2YY)pm`#l zVv*BNLwkaufd}YD8_VcM(iZ)9J#kZ1NW>|TiuL*0-`?0J%q>F+s#QDdLl_$Yu_nag z3&**u&}C8OIdZwps@Fxp+7vq%KVU%m;Jnw0p@g*_RT|eUgHx%W=d^(ve38sob&#j9-t%*Lv+Y+ml8Vd&7 zx$E@8kOYZ>wba=Cw#7vf%z%bgCf@3H>xSu~+9_6%+wu|!2;2r|-(!SYL|{?NvA>A8e2sRnp19hLoIC=n@1$H^*}l-qC%{oiyK>| z{{YttWqHgw#SoSyRhkkh>Js~_s2iWCvA@jW%&d(WjhRX{x($!d5USc5{Fb78<1LY% z7LgKKdmBm#HzwO`0kJr*Bs)&vtg*Hzsft3k)-4(Xaese*^uZ}0RAH*pE00h;Ha$OF zG}F|@SfS~pjiimN$$JzaotS?-5CIQ%xE;-}sGk1-%LK_)cSKrKlFc-dhce3}i&=@^ z^}&^O)m1S8B&rwyy9*KN0DmAb%@H9ck#%SVL2sG8zotBAkdNH%z=kB9@s4$=b8I5g zHws!=QdtWDV%z@!dttLTuY)M0GrI?>a$~2AwY=#x+z)$gbM0&kSDaGNv7V%ZIXa__ zcX>!3lmUhqD6<^zGmfJ*RTT8INU0D&LJc4*2Jd@dWS5{$hA=s&z8a*cq@;6N?NL=S zYj$QNv$K-S#Qeb+ki6|2dK`%hZ+~nZ7FMm3*XK`|<IMl)>boTwzU6*=+v+hk++&wbhM=fNoFMZ|8+LOFB&6ilUmO)6(aHjeZEz-x zAIom$;1F>_a9C|$Yr~ne^jC#UXroM^x#&HP_pge8*f!-f397Gh8tM->LcH#8Nbi3ZtVfHdMZk ziZfbR>R_eJ>tfaDlt()vxCZuMqzyL%Zku7Qw>YWH8LH+Kbn_V1U13cEODJ2PnYGW% zliv}oXd@`al}m49xdVRx0Bx{$l3W&q#v)c&&CSlD3F+;&B)BZz;%QM*@{OHz&-@XKflx8dVnw?b9Yl&%L zXvrnZ+fn}jF5CSvUGww^{2|Px3^fZJHI-2as|hY+x27}~01tkE;6-Vf%gO_5+TCro z!v|(2Ws*pZnd6b7a;EEWNbR>#{O}V%?Dx~BO|A1ETt7_O7EwJC#e%6|FK*{?fn}Cr z05Yq9ZUA5DgJGtss8Q2@Hp`;R=pd((o>QGW>tb5T6m}y;t-D-; zP5m|lxx)zul2~vY)MmXJvX}7ZOt6O6rIzITkJAzE8qU9KL73C%@?@ZKPT+&O9pkY* zE)?zZHpHnCJETs`$Ey;0Vmn)qEF4Ego@H{FDs_2MB8!@czlu8_%-f55TKLz^9UBSp zdqRqm!5NkO{aX{gt$aUGK_~A7C}n*lg}uv*4^6v+*552fvij<5!90{cO>BEj1FfWt zZ(>J6HZ~({Jgjqxq%nzE?54uujk}9|v0^7;)Rt{m^Mw3MbLWF8>9W2U=N~mVYK|+a zQ)T=`TTc>fe}yCf0jQf=*C!0TZOy)Aa~^1$jCk{nIKpL7XUwx|ilWRfq>(GIxc3&@ z7W5@fZ4}imf_m6u4^yVd>D)$3m*7*`QCltdPtdS_vz89HS3Zt}W_tJ9i3wh47h0oFV2>ab~r%reXU+nG`m=@Ph*Be!W^>4RWZn=fwJoQS*f5G{pC8M07zxr z0#86e^$o{NADG27QB=5$BnA+Qjp`}^195A1z5vUoG`UJZ>Ka%;05bkv?02^P1|%`H zRM80nq|pOs0>rSrj^BK21F0<0Pf-bAiX|^Az4cl#d-bpc<66EibF9NJ=9Ltbwd&1H zl+z)GR#{?^6lBifZay zzOt3*Xd`u~n$eWd%V)Q#Eqe(D;=zYQdOE{lY`91sE>}hW00Jp;45!0?JF@y!%;+9| zKTj&2G=7ogG?9K_G>ce(3F(d7NlBB&?1gH}4UOs~QV+2Mp&c=&{{VqSB@})cIjGQP z-?XV0n3a(%(m4`T#we+`b88YWrsJql*RD5j7Z9Z~2qLY?8Z{&@on95~e&DILJd4`+ zgZPZ5y01_6asL3pvb>ivzZ|*|nCG4!DcVIUygkIlMv&LFO$OwD`ajPaCh&<0#ljiv zligQLVP4h&{OJoV?Y+K!_}^E?*;Vu2MLiX5B}{+%dx_WtZCXjGp<7&U)CT(78ZGdz z6R*+{JGXbRfy1I6{{WifJ-c~2nFqOKtH{hn>_)D( z79T7pB#Obx*^Q6i3zgZzTu0Z~;B*SCz-n0tu-m8iVUCfump3RW*-`gPk-`W+)|6DcX>s)9#sB7@B>t(h!30kwt!?XF0gELw(3!=NQR`Er^T z3|KOgc4K|*`rr!Lc#eXSl4?qsYh@_wEK;tkFmFi&3)@K_af^u+Z7+9>V=EioOCiN9Y5CIJYw^$bWVbe8CCxUseZW(#lvvye^6`hT`1r6fNn zhVtE+pK!`aALTd|6-W+A3a4@MxBTLu+DTwFHM;Z|L7P+RMK;(Fhipi7tS-teBtoX) zlvsY4uBs>`jU!1A$DvCL-%;)lzta`bR4qKFVvy7(heD3G1Tx!k_v`Y)QI%kPuprU5YBedWcVu%LPSEMqN=NEAH`J1#^GRe{qT`YpST}DwQLx{A^MnS7UT&w4Ga8 z_qi6gYu^(K*}!EMI}e^bc%dw}MQM8zy{&|ZhcKtazG;p+$Rf&Vr%cG!W)eEBMInWw zXqQf{S37mM`P^ZoOPSR*M9{#d5=?1hrO@@c_qh9FR~M9mybWEOz})D3MWt z(gLU!0@zrJ&ovE{CaN5oG?3Iw12o=P3|QRW{f|+H`e2bV#E8hfQJI)(eebtR z;a8~984DX+9f;rb!%3u&bm_Pz-3`ba_QlDl3|vTs1<$`+0W~}_KA$NFC)<7TRoXf}$yN-O zD5hMKKB3HlMC%lF24NUy)KWOK-^_A8X4d&%71QSRbJJHP6b7DeFbGQ~t!$>(41X@y zztmyQJiTa`c}p4={J}lXTl?UxYVJH8k}y)B-du&;UUrzWqO338pre)+`3r4X63yYXYgJ zSYtrw!^>wru&$xl}qsLUkunItJ3-dHY+q;5AN z$EV0)&npx)RJn-F>MENwgovY(XJZX2fLWPP4^uHV0PF_ibFi?4ZUCEBl2(j0)!0gH zb8UtQj$kBHD(VZq$8grQ$J-B_K`vWUm`K@e3(-=NN`^OM^KbSW4Z7ip;b5sDxCD{) zw{iO5JTgvH@2*Kk%b=NsOffY@N8$XKNqstfR~z;M?bD^tz6jTt(3PHAS!!U67-o@N z7G}9^NxIoUWLq2Df^Y1U1Vy04^Q(>Ts>^So!?RVeV03CFOl{mUp4;Li70EfW-!wi= zo5oi-uUcxTjTJbRmc@pt8DkswKC`#7laE(2%w?W9D6&-ZSli5zt~JHW%js&e ztg|}ID(KpoDi)1kNuaTmGrNKnwlU~ZLFv-hz_V6)sLxgAIX<}2Kmgj-0^IS}_cIR_s1wey0BbrYfVQ74-&J5wiaP z60+C}iw%Xh{{UP)jIHO6C4~^W09lUOuWtRx-xi{1YqF}mn^eO~D26joLV~BtA%8Ot ztABf3{W=^U3TAY2#T_&=IcXFv!M3wv6n44mZ=NKS)G@)ALX{Ng8Z~Bwk_$HEHHTe= z{{UQ3LshRZr%^RajecgIo}IdO0_PT_Xyz4X+LF`B88ooX2%er{szv~|mn7cp?|Tbv ziH$PCustU@!S_M(}EZ7oA( z@IzHSz*_`wD6gd0DJNF@n*nTWMhfbRc8yXdsC%6$x$R&Lv9CWBQPa=I)k#$sT|GeqXF7Mcy|KAOH0+VHv_Z;(Y&Plj$CNu>@A{P9_34h!I`na$Mb3xDuOrK# zuH?Nv4J2_^Ckb&Bu3~bexUZnnz<1u_-NrN#;gzQxJD$x^s?vTPEPsTCkbkKAV}73- znNe4j^-)#S!+s6oe=%7|H~em2-?u@z#)^DCM;h>i?iXUf5>4*f?r-ha^v7@P3lGpD zC)eh72$#xLD8P|&diz-6(lUtxsbKCONC5Nz zTz@^V6GRNU?#iH+x!jy|cM!SBc2H6RFLQR&)DGL=H*yv10VG^)(BR6J4I{x3Q|h+I zZ=pB_NWdV-$4|)LY%QlMNJ%7;C^3+u<_Bzge8jO}B|QheJdnm**pMx3P|N}bBX{+cp%n)quV#87{2L>an=6z~l?*mvSzCR{P-@r*PU3dPVLp*K7v!IaMlI$UC3( z#9ERO#iIvHGbGJ_djfWg&29Bm2SN)d=p)1Ph$3OOR&;I z4Tk%4z=F=gO-x-*pOw2{mP_73S&ru4EDBf4bsBWBvu*UlHds;>PdQh0)4jg9@u%16 zLFzrgx9fy8>e5|8j-74%vEbAsWC#^O-+V(J1`szT5gJIW3XpHq3{=cO5rL&waela> z6Be>0EP#STcD=_>=Y=M9AHqNz5D)XgJ+>`4I+aCFmQA(XM=mEM9ulsev5=b>Jl~S#?$EVx$$I=yI0rh`JRutK+EBR=JTz3{~< z(Mc?^tZegI;5gZPk`K?@4R!^r47Bq}Cz}jTCB62t+pX|Imt?$pEZ(KKy|B$qRU8bc z&WW%ANETa*jsE~#dskg8B1VEYZD*+L2e86KmKJQJ@UB!emr_OV?SF6Qf*3j2fC2o# zj)&!dX&9s{C4uj9f1QpDGNNma{ zo^LWj>QXQW7r$R)f(6E>xjXN3*5iNm!L-tbgJ`#A3J4d|^4}h7L;x^i8^2p&6##(j z+Ejn1z7&Z~M3#-CX#y4i;Xoe0Vehj{KNf@6b^+|!W_mOK+;6x|_RSQ6MP!3_L|y7=kxx7B*I}I?kI|f=K-a z8XS*EXH)XE?}{S`@-n}fZI;m(oa9Yiu{z-{t)ABcz3)rl!;cD#R0O+%NV|Y*uq? zAz*C<7>+;1d4iz?2&rMQu-^9Rhg{Dlnko#rV^nyhQ1Jo(08z%Gpy}!b)w=zCu<%u& zu7X0MMQ{TKTWS|1j6X?F5>?XGloLj=G$l3ZXD47m>;US2Of{M2p{@!AN0X$G76L|Q zZ2*NKVm801;4j(L9(aN^W^GpV3;v%iv2jIZBrsP=A){2Y8IeWpVQ;5Fh}C9emle@S zf>=sevwBKx&>sD+a4u-OM%PkEMVV=WI+m)M2+$%49FU-F03_@zY(BQdc8(^B4Ix#A zrVrSA-}zuVD)`pXv1wMsIAeWF?fo~!GgN*iW%C$D+nvs!54Xzx*nk1blV>VV!_?^{ z)pD3rMyRgnZ>iekg%>*wjnBwpR}4fwV!c0-@v;-A)Jv0lY&#CV-Ej)a9%@|1Ija^) zU=g!O2(Wbm_P24d>-NRaq^g!`FUP7;!ex_JrHo-VxI1i3g}3dDZIvW~GNM)ajPX&) zJuK|*1HkXLtKR*7!2Ql2I6{W4XulCzmq#bjrf#9 zX<9|np|5MD_G4qQA3I+f@8`x>`%9V}f2xjIDjJrOt*LBp2twhtY<(qFp8m%7-wKiS zlD2vV8@1B+!Dln!+Fu6Qn@wF7T~9w9=ZyfX(dImQDNm@C-GCr{w%XX+if6nkR1w6y zF-kglW)*V3{ubB9roIe$)LA!!x-7CRk@FnRUNg_-nk0|@j9^n~^#h~=QH71~Vb>eI zrH3tgT4$Rhuc4KrR%oO`SqT?CKU{fZwGQ3HCM18DuS;+Pw?`QCT*3Twvn;sF%2uh4 zr!J%%C!a)ApYzwyj=e~|zMo8Jo5PG$^6;)>I>RkHG?4&Igo2}0fgO)s{{Yluc%L2D zi#W=;V&K?Q@V;{*DMP8-_N52_-{-gfF{7Ui$YJ3u(wOORWr>x5BG=V*zv=Cc-Pj<1 zv!lOXn&dsSdq$!`?pYTUP8hxXzy+=j*rsC1EPCC5zTge5ht|tp48EGaIT5L)UH<^= zH`?E0i2St-jp`DFu(AIDQIEfCLgw|=BP}!2vDXu$mIMYJf4hT#=27N_AyeFY;z0wh zV?!)83Rol5rBx45q;2%WV^z&tEmTx6q=<|XR%RnfC)>E|in@vGl9n?ziSy_c z0=q`nH?iE}h6JLfqR0ucBXRe_ z#a8JWF$Y$X2;TP?u2|Q~LXUlzGTU|E`Siom+*5h{#RA=c_t=b4<*+7Ih&aDOdSI79 zt#zLzSOcs4!?r#z9+l8sMnM;-06mXG^v8=E%OOy`LAU+K z`@TISEOMy5nCiXv!$nsRzE0G&6!eXmNRulFlpV<4&HCacn`3gA)>%(+h@kn4%m)9cEBJ7OQw18Cx&ei0>MCY+rLBb* zN(Wa_{69aKAdEN?C4evjRO$)b5IwLmvO>!Tm|2LvqhM9OXBL_X2G_n7g2?kBc-St$byoR<++muUl3874A&L@9hPb)* z!;YaFi@K6F(_!hwhS*B0M~yyMy@L~T@;E|g3e6phC%y6F&3!}yEN(r|xc>m01yxrS z6trygGG{YP>X6Z)A*zWVkdgUR?{n-Awh^h;HH|6pY0Hf#IG*s5G%AGzu{Kp5cR!{S zrK!j-n>J&f!fd#@d*RcJxT3e2Rdo4|d68sXA5mas zk1Rs1P(rHy^@-lWKmd04z8e?t_msy=4LdOnXuwc@!)#a6zDWk+DK=&`m_g9g<@to^ z8s^lLj`Ac(v!tLdqq#OxEH)(ezCJb7(lfL(M#D%XGgzs)7T@QGku+e(<-Dw+JzEO~ z?gz`J6pYbID`Tss6TtD9*4q^%f*St9*SCL{Tv+hrtQ4@|LPjcvYGn}=ks9C?H|>QZ zVoHWrBjzn_zIaNyni^URzAhU~z{--evYF~tmPqV&QDJNPPyYa<2W(Lb%~Zin`%9_+Zi0LX{RDF0x*eaneAcauwl2z_x`wAD3#dgVjOoHU~=q}g<{aC9-uoP z^}!D-JH#T86d-ESHo59Ca>)r7SWc8wwq`N*e^Z;LPpZj8Ek~K3jHA7VSal}YN z>QX)J*87dR3t|~Z9CBJAA@h_MZ%MU)?TKYOtu-{$Nh_o_AzelEgSOZb!bJoJDoL2q z#FWv^0Ckv19T+b1Y)9Bw1NOuNG0$$YK~9?IWeU;*bANA{z_l5@QdG%HLz&A}8iJ}^ z4K~xKYy64CTQsVNB!OzBFEU1|!BkzDuduNCeQ+*z(Ud|u$WN(FESHk6%o>{J!@d2x zVw&97Bg<*#TD;3HqmiQ$KpS&1@3N3>cGwS?w%CL&S(#@PqO&urs>`LCSrSaK2mnWG zqe$SBs`t8$g@=3MZqJ8$oEf9Hzsl%7h!1Cdow=e#h@L-?G* zR80ty9YK+0Mmj;cU97;~_UVV}U)f${wA0r^9Y`9{gsKz^YOyBQHn&fFJWyoGH54_8 zM=XL$U`rd>cRy=`ar)ttG~uO^D3)kpsy7Ne)B(lKhT_&8h6o39P-rE?%+VPlnol4; zf?KFI>2IMJmF2njkwCPy24!_5764hjjk;}be)xk{<=Kv39Xzzs$yBWD!XV-N(f|Zp zn+py7@hHk^XoY18=Twr{QQAqQj*_QCN~?7tT!U*k9k&Wcd*Plj7+B^4EGv~kR@!N! zr=D4+mLUXbC?ie3j@PgkKbLN}d7;as3p6>>NmEm*>l`m(y83Pfx*h)e^u@l)b5k1{ zT9rd0sMf`F779Ap-rr1IOsLH5C4D)lkcb?XQ|eaeE)Dkie@s}66P2%UHA{MW-^(h?eJm|J=_R37y7*&Iq=p>}|0F+T`LL!cSeB8FM_s zoAAwLjT%P%+%el?2f4Fc_uCT+YH4ZnDIf7Mc`=8)j!Kyx!=jUN4gUa6xU+T5IFz*W ztkcrg&rXRz0-2oH*eTfUZrz2gdt+UE+v1GwK4SADG2vQ?5_w>yr)G*BW~Q0pa>#B@ zq$0qBw$`^pjgG+tkT`$Ag^aSHM0=|3d-oP2`W$OtjAV|Zin+rCd242sMw*Ta78NfL zpuAy><3RzP5;*`5x9=}vK*eX#G_7c4qE}WQ1$3o@!1hrsM0Eo&pNn((WidvmmlZK7 zvFv>|9?Olx2_|3~J{qZ&J29FdPuQE|P#*_s8p=Nc+_$fSt1X@h_=`JtfnHMa+Oo`! zRB2Wg3`X`0yWEkDx4|u2|iCo&NaIMQt?c{RlYieT#%QhQfUB=D6=|U3$qHd1K@i=d6P=r^_IvmNr^rCz_ys zP|Pd|_Skg5lEo|q>8fEXIvp$kxEow=_ZYs}#dbqBK$FwvG?dKog#f4`dkwXYp@S{8 zeDP~4AF-^(M+x1l^ik|>ZCc0Rx#whkw;*Rv) zcn6l8f6o3Ci-PI+rb^Vy^4V(=O4@a&SecDVEyPUAFkqUPfTvZC*s$ETNfjxgR0^p4iLZ6&@6Mt>F8P@=jZGj+Z5(;|k1<1!ArIC$IY-z7!17nHWmyx4nQEjOAImt5>EJ>mQWfP0QZFMui^W0G6@oYhp&S zDIrlpmOiU|@a;2+8CfGUg;cBzTap^q8iw}8Hxb*+H%peV8(?`aBPn4e?``l*BT8r_ zIRe1jd^yIH^ulS)^Elw7c5qUn!_>?yqqY5w?fT-Zj+$y5zIm&Ve$buTX-f_F=sv(; z8mctSb7~q{VDl+-vq^RXSQglh;D4?kQZglW1x5C-w&U9rOLw?hoyU?Q6^)$)lC!8& zbsKN~*T9M-c{eI8uovl!mgO&n4tsOgf_aO~K2!4BKI7gT;Wwp^h(BeanyQRWlDu*) zF#Y7IXdJPOF zlQJ?5Nvmzh?eoI!j94&?75d;gRRZcaRXr42uh;L3<-iImyHhrOo57M$OU-O!5#g93dQ87KK7XF@FhFhy1e+H3Cvp$5`QY5gCa2G-Gd!-oSl*QcK4fgSGpU(% zD(*jq_xW_g%xoCnLR__g14tiFVU1VOgXY|M1+p^%7S{7iKbtD~mpYVMcwgtII5}_3K4@~YmmERIydT1|(^GK_xmt>foVU-3 z-$?I&Z=JE0Tw&m|pPUupw}JdtXM8o4#mMd;sEU^@%;U{ql4&H8NznsSDf3lJQq8#* z*n8U;vqVibR5BT2L=AJ?oD2Lp1+ar&N!yEggkEDMB=A$z(#spPu)`#X!0Sm&NLzlL zNgrc|m~|qwYDiK=z3snjd6z?2lIAosgm#75;e8`ivE2Ha-A?^Z=GZY(IFj-@Je~CQ z2j}hf#I)fl;F5|m2#4Z4)DpCQTy`A=tV#LXrYlNvc+| zx8(p0hTQ8;-XPsvC zRMnLRH;Rxat|-yKyoyi%08{vHZGmfbxEnpJt%|QJ$snVeb5!Z)J+9tX#jW3`QEq_Z zc}q!2J#z<&)DfTy6l=1tV59vpSUYj2CXqoO!_+ksJduQG9hePA)B(2k+v;&Wq|386 zg{moQ>1>M35Jr5-H~uF2>9Og)*b;`0s+yf;lB~9&=qnwJ1h5_b?c3b@;$b%u<X;O!r3-veQLdn?)lU9N|`^qbkelQdms{u^^e9 z3q$4Ix}84V6x;s*7`OSg4q=kl#aWWc1euDU(6$AhHhtL-W&~LG+}qz1>V71SY>KBd zs?1=h&5|Qa5D^quC6Jpwt;<^70PZ^D?3ae~Y_)R?!lt9~xur!Z1-#HBQcAEIjk|y^ z?`w6%*TM^JRAD0pTi0sDrAg{pS27MnzK>BL4*mM?Zuq*q6`RQLR!eXFY}v+Tz$mYJ0#W)c<`EL+w{C#S1pZs!vY5*1P(!&1Vv6H3e>l)jdYg6>A* z>)+V@u-FL!Ot@FuEvd`R6HQ&MDNq6Xxcy8)Iz{)rhxNpnE9o;Sa>a(Fn4u)ANKS%Q z_qDohx%+m+HkyJOWu~mwQkmoZ;+7#FrM*|TP<~x7zFCx148ly)FRyxvNSIA?u_cnt zr1uJJ2mb(XP4O?1k_(AX*>stzW*KbZYf8%?0YM@;Rf!iJtS`CwV_n?Gp%ZbBFyp1o zVKr4XlqDyC?Hnr{gG+#*hBjlQ9fK{;TWo(VlCH3p%qFaO;|yR*WF$h!He(v@LAlsp zsp;EX{KcY%mx#H7`s1a7qdcW}0wXh~h?F@id!VyjLAf@yjgB%iZUtY{5Eog02q;@4 z@EgFMeHCPxVa~XcSkWRRGk!gQB!Shmfq$kpS4&aD8J#>;@?`n6vPd;Hh~)~c(5Sch zNYj4y#=E{0amW7v;wj3ynpyJ{r;{_!Wsu1$t>t{uZ$jGZqy z{%ef(z5f8l%01s8ucOjbR?^WLEWUA1`Ae*4a&6Y%Gly*NBV3wFcaE`~7=)29VoJ4! zz<26)#r3A5rTi305|<}ghBYNbEWi-J+ka3O_QZa#g=r3DmB^Jw7ZEX$4VZ}$zlBdu z_XpeOkFIg0@no!Zu7XraR(6#tHa=Ufk`4DCOh%FuGmw)MI(=5_@;JUcL6K$ku~$z8 zNSPxfpG}D0s*~G%Sn8O?4NY7O(?mkDsV(Y0*Emzng!pMSUUdvaQ<_f?YtwpSn zn*tIoDe}iI&Em(AmA?f{o5Mvn9A)F4RJ>rdb8!5K;&V;=W$L`-Hqz0EolWo9f-kYh zj|IOLZxX%_s&eifqs|92IY_J)P8ZJVBzS38Ron2BZuHG-+Sg0SJq$?f0Tk}Vp6nw18VXMz;Vx&VFS8)q@REX5H zl1OwTfOQf>HHgxr?lVKf&xOuLcv;~1I46=^zR7quE+KyvP?77b%wz-prBy>-NnG{2 z8+!qcOg=2X5uQ!>(&f*FOy865#90p(WYw9)MsJp85g4j+iDZtHL{e1ry0MAM$cFx% z!kw_s;G^T0&;CHZQ^6ecTHbzgwiH+rO1gzi<1UO?4<@az=YTKhn&kFzica8K*XUUr zT~&79wDs%urj1-aDRCcabpHSlXcZnecybV$O7i~zB~az81?p=~0$gK~NTYbn~EdRmy?q{|GkpUTVT zD7Ym}_9q&n4pH8qGOBJ#JBwrLxO7ftnT&o20@k-vwbGK+7U9}S<>Fo^3S%&(Op+V8 zxv(7v-xCR?NMkYqX4Rx$-w@s%o%17Go3f=d$uY4~KyKgYF#iBNix`hn`J^zDZuZ`}g)gp1^XMw^uv4)iw>P#4^MWFm8-ZhC{rs^Wr>ho~>;x264fw@ajQONF8OL*EGzHk2kIc5<7 zzn@mSs3-Viw#LMqe3q|;>mS5lG$(6upRjc6@>@7{F$e=)lDcU4X!vre+Y`=*(mXf`)$(Fw^t&Q^+Z3H@ieIy2r*6P5i++P?Q77t-l*vkstwHpeyOmIq1o6R^Fv$3VXtPHl4E znjEP3c)`owGvQ7wl9PcaO2{(G)TwN}-k&Q9l7u9w{mg>Q2jxE4&?D(+*hZR-zyKf2 z-!HFBeK!b+&C)bDQP0e+cBpQUkelOuJV{XuO(M$h#pahc0GJelzj4#w>xJFWNZ_Ecy#b#$e$9~ zpE)?1wx5Y>_=75&DB=1T4Ar@$apm$xOkmj+M2AZ|HJ0N2abdh_{Aj#Jc%fX|f_NTR ztuY8&x+gncyDRtqza`y&Xx`nu!gCgEDiIE&_l>~1sm4xN5WXY`1K0j|mZ zt6F^hz3c4!0C?TSf!0s4b7zRcRq+L!r7WiCA zqu~|t6q<68MAPR1m@eT?K}f7^-0sHTOmh-y=B$!Qr&+%|D0`=L+%(=15hdN{Ur4BWX&7Roq@C&|PoS z_iS(T?cO+JA<>Bn*8tnL4U#ydtIR9XV0@_(8-@d5pjm8pxjU26*lJX0rBLOaKRWMy zUo-ay8fQnEBl zBxGFaJE{3%UTH*Tii7bEVH`Zy;ON?q$?~b{BUuoUb|}OWdURv<+vkhTlYSyvI*%wo zF8XfwQboHS*t7g(X()Jyg0oudttqT@5|jBQeYXJaq-ag{7r(wQcMjI29P`EHH1Pyr zZWhIl55Ol&W6YSoay@U>hMA=IR`u7q`6`r704`r~GQ32z9TFXErX zH7vZz&3Jb&%x!W{b*FuBu0>_dAa1;&ZjIxVhU0pOvA~FqeuJyK7D);RzKYr{ZoL2%Bh*z5uEK zwSW(>1GizfOmgG#&G3!G`EGxc_`c-zM-EH-Vzw-=j40@8p=m#8xYJKwh^#|-iiRm| zZ(2tC>SKqAzr(-GfaX|yR`6-DzK{JWT7d1)kyL+O`t-&<_`CQ)b0fmS4%ZVolunHM3PF%0<@veruGC2b;rkWSTwL|8u+yqPAZOXqTXwD zGQKj`NB4!Nt`x}WsQ8*}ws{|lD-AlNafBXRWU7%X-*Bn8wXeU**t&JJ6+AmVeLXwU zRLZg`9UQ4PDgw6QbzF_Tz3~d+IkNo93jDv!M9ms!s+h8X(1Z%M)%l4xE55*-IagDq zf8!pHRZUy#WQn9Q7FD(GO^CIPk55V3-Fi!%P0IOeCD~SAG^W*_;8tCJz}RF^XLARhMUPrtapi2)Q7o&gzIA(j3zwiu&Y$e^)N4z?F| zTMKFEHezqk;(1FwE>lTCln11jF_T#+Kz%ANsrDAP-}z$GW%`(LIO7Zt%Z&NF1r=Rt zPsLQ4>M2kSawR!sM!mZ00ByajaL52Iq}Ceby0`dS)MeRMfi6oeMO2j2OEz^@`U4kY zb4iZwY(Bef^Tx&@%<|`rT{F5xR=WW8iF+OY0EpihQSi#hVw=FHBn?D#l{GrEuQEnp z9pCn)O8SWw*=_vKwlnGsx}l@}?KN}AtjJ7s!%4FdwS}#=Jlom^1Fe+*0I07?@M(XA zkK7kAzZZDqnadBA5@yWovcS)BpY9^-yM&zun+90UGMp>J=*t=rpkTaC9x`K z7cI-tVuM`(Up5Mh^@)o%>+U=E9dTsym@`Q8n&xImzYqk`Ooskrfqjp@@wPLb5lYs-v1y=QZOs5nIr9^f^a2UWXXv#JQeFOI4Op2@-0VT}m`Ba|4Tzt=O%K z*p9X%A73B~;Kt%qLou#+qOM8lOj>k+inb(Md;RzNV$5+Ll`d)cxQuF&C~YU8x6cmdDo^hak4=xbEJpo>ueKmHFsz6os6#3;-CEn<X%DZkNdqW~Z& zGs+4`^EIl=>uaQVbkZ24BgmIs&!n3&xY&-nDIGA2Qe`qjQ(5@gR5q4?2*6iU)G<4P z4%lXuKMNs_qS^@i5PRG7z~IY6C0&6zLjfs7+{Ylj*?va*j8V4(X~&g>>6)zcHAaXR z0e4mhXCB~TyUhv%0HmGB>@b{zQo_ot#TV3XxgPuAD(THDvN9}+S68RL!wvE9kQr&s zsx_eWf^Bi6U?-`KB59nRH`?DL{czDyoC1{T1W|%R?ml2xU+O=Z!*o?OS%g76q>Pda zH)XZQ`r>2M(8@6lWTz=4dbx*`Nn3?KA$$d&Ooo|qHE@zudL5SciaU$n?fr38c4hk> zfxiy{tgU48K^F^afqUBh&J>}e46)TzGc8#beM70~{Vj#L7$RvRfU1+T5EPBcJ^KAI53Z_`^B|A_ND2w;I(_jr z0*129s_5z+B&LLh*1C=R9^caw2&y$A#TaPF7CUU-_=8hREkvQA)LC^gHtcPG>4_B$ zM4od;G=YIqREE91M0LV<8&L3hCzhv5w~A9Brm9C)hEffqVbfR3Vh#?btAjbF{6!-y zg@L_|im%)|x+u{HwRH&6J&6;W10D#w`R z^HJ0lxk(bl9)y3V+a4*AU0oT_4))vWd|hM3WhAqza7pGsFC%IO+DY2p{{YV(iCNVT zrEE>EZVAFsH8FA}StTTrw%f7XpRKTnkjMetZ~P;s*phQ$Lt`j~tda-wY2_&@{#H$n z_XLlzBMw<*URbl`<2Ie?Qd)$B6$0T7%_jRa30-8e3TqW9+_m7#h%JK*z8BWuyG0qNF_KVh#55#K?l#khx{xrG(Zm@^uE-{OdaLGQR*n?% z$z?uXpy9d&xYB#x*ix3NYKS44Sfq+uD@mwsJ7-vO-~Rvf-8 zu97)3>1xUmeLswhp#ck%Wzxe?+o`qp#<}j;<#0CJNm!~hGX)w4yAIdGvem_Fq81x% z*#5svN8=@0WN;FpPKQmHsrK7z^}(^anBAFtvbQ$B>Gs9O$zsw>1gE%X2*K_Nw*KSg zY!tN)btM)|p#2Z8azoNsSII+IM0TBf~%`T(sHvrqF z{{XHWvY4paqA6=DO%z^gMdy_-(VIMpXlL zAweJu+fmqG2;}@#TTeAq@WD@^!GI*O{{YjEPgV9~adXoZ9!WSx26DVl#HDi6O;l=q zdTzr=fBWs&p1a^EcE8gOQ{ zyk^6DY{uU&PwH_i;as9>TAJmql1msF5U3?h_S9@YPpRK*W1D4H1O;U{%P3sqh2%wO zp1v95sf)}6kieT*4UYEP1@K;dE@hNcR!pq9yes5YA&+I8FHpY5_qO<)W^@%<259a0 zeKhemnHwF{_8)!mYx9K6C^&_9iz*V-2_q3zK%+`jDA=10j4T))rpN1w?}f~E?uqss zC@aeiM75BzW_dM9tEtjyrbzS>0kH)KU*fmh8!GT|@igYIfo!LZcn_95HNZLl01xLm zjXq~o+0_*9JTu2mw7@BjL;*A^8xT$UV_94$#91wEL^Ks>)I=AF<}T5^15vuj2;8lJ z2XTqzK22MY%-?~h$T)(Ex>70Rnr4-WP`{jy;nd1S_9bzX!5pmHAh3b0d}i8mx9)=M^sXxqtJK#_-u1pfe(HO|KD7;kGg%X}g}38ZNfHGmL}+WCm0 zRBs`ot>J@K^-uWv5b~u=HeWU^EC~U|<~KcWwx!z!@osHNkmO})bjI}{Nh5$%JPUm! z5&`v=u(01r#1}fw9+x%}fk#u7qB4Y#`GU4p46P&YeHx3E1lajwYhoFk=GD2?P@6E! zAeMy;EeL4+RtUkgu;{m9G}_w>4Y9E#I8aE8I_=12t3=A_>zWF<^O=`irQ=k)F(r=M zk@-gbt@6QHV$~${bkoN4H@Y*G*b;6D>wepN6Vt9f$|yf>%`Hozk`#nS%cz}V*8O%D z`R|L{!W0n-ZBx?0QUo9~PA(JEUGn!Hn?lw*n%yKg~Pe!HgOhbOGynwWmRme8F>P7?OBXl!pZ@^Dg-dZ-)3hQ> zMM|cYC3#p|VvQnzPU8J;ahTi_UzgD4lytN*N1b`qk-%x)33#JcVkBO~>iHd;>1(*pA8XBH-g?& zhpwciuckS~UQCV@rkvWTM!3k-E)dv@f-Jz>8P^;&G9pP$B|Pvj46e0{W(U4Cf$;O? zjZGgZd2h#YNZ)~|IgF7nm+Fv1npHz$qhYC4iDGO8g^4E{JeoYF2^uLW>7B){LPiHp z!0(SW@zOq-E&l*9`L9H9R}rO*`UTAA#WIujoi{MdEm9$ig*a+p*1m!>eB6X9+%UL4 z#Yea}(T5?Vrp#fdiYh@%Q5}4a@+Hd8p-EP;=tiv_H?TO~-^52HG@JqAGPXGDrl6+b zP711Lkn8f9vyARG^&QuJA0ct}&}SegdOB_;c`5=(*@WU3V{mU85n?)b-?6?sA7lt; z3V;tI^IWU7e&>-uvPK)ja;M?o|xOJDvXr-D0vPfjm0Aei0$G5iI{P4{j&;vS1BrF?9u>SxtH^1`x z93VWBn&`TOHB>OvQ=_m`CzcBJ2ipwNd6a7LdL6X&Bc=O%uxVn zC5lvUDV-P_^tkDPaHWiC0Ww2W5c!UxSp2yVi|KD#fxo_zE)UNI%wd*_d8J6{;ci1Vp{{Gl)llO9%uI&c*~0 z*kH=2X{)K(11q@P4yAeyn~W(it(18>TAjSYt__1Aw!quuFzm&nK_#@?*l)fBc1D$D z2+JYZ*zJ5R@li}NUKh|rDP@ea8j5iVga;jnBklRWmMD6l?A}PythUlcz_#0-_^P6N zYJ*8o4Z-?hsiah0QY!>wVQ$y9{{YJkd7*_ZZ)U3}f9$ALgV{RSgl->rxaA$?87%EU-lntmwbwxZIxS^caIw$3L1hI~yH0 z2G}w>!B0-1SjjcYk=DQ+uZWG-Y^ZmdpMEA+xz#yK6Dy@VCcjGb$@%} z)QxRjsAo0fNl_&vjS(#%me8uHVsHLybm`yN`$^L`e)b-L~!x{#%SH zl?@D%>6POw2bq42ZlBcPc`9HIRh(_qvHYXw`r;aBb5iFHNR(+Kf#BIzM@HJ@vn}nv z{{V%5wib=!c2tp;Hz#kO&j3kX3lOn|5ep4xx6EO>X#sXra`&+f*Z%-G67&H+JzOBj z7@&1lC;rkfJX52OQu%Fr3vc$r0#&s|P0I+i5>y@U{qKhn9IdKV3al8lyPPw|6@+1p zPabkeLL&q{PrdMLdSus5JF(NV3NFyDNimMh==CF>7o3wjU#Z{9qPP0T(wtk8Bg7 zY36~Bb>VqEbd_&NE2!uvNCbgz5JqCoAM>u{Tv&SoM|>s2%}O=F#4}gHrZ;m_1S=^Z zbW((i+=4C-akkh|f|k1|as_}ms7D!AkX;xRxbAL98($3rCf zlrJ1?%wj3!6Zz7{_tX6TSo)&2SQS=}Q=L7Vwo#Wp54f7JZUc)Wan-veM4+8RB&+$m9@8FeDY| za1bpd_bwAi-@Wld0u>@7fA6*&VGy&}4GMab-vrWH5Ej~{BhXh#1<1Jh;o2rj zh*FdoQdJuhu{)ALKYsq$rYdLzQb>}yaK}<MJo-fth`eP$49cYdRl6Tk6aCu^IrdpgB6;yg zs*Rh<6FTYE#B>0C4^H>DOXD7FQkI>k3mB{DXYB@FM9LQ&dFPD074%O6I;jm_>su-j}oOPA)CrH1(6!79GC_8zm+R)Z4Uy95trk1eE-jOkA<6W#24TpZ6u{)xn zs?QxNC6a=gFcf)f`Q1gyDlK3vFN3nohbvSFtvtY!r_KI8*Bc9BXqj{iRYOLvPvtpZ zJ6vEX2K(H6he3-l#Z5?(Pla4UG_gaK;5q#FLaa11$q&R9S{PwtiCa7op0mqi~sE? zK(_jh_Bg%SEMJ7qGFh@XGb-$@W{9-Xp#hYDzFQ4}KbV2n+iT!Y2Kg;_AMw9A_zIc~ zx|UhE_Bm>*=rts{go-IxNb1D;%S&>rV9bMHH4ItN$Qt}Cke$B|n(1fZ>zC%#{tdY# z@}Tn?lQXDT=BOx$@0!-TEt7kOVmIq;y5AX!k@yIsDg&*#4&&)8Im>=J0{Y zgE?A&`BiB$D=bE4{ij$Ans4b2Lp{3&+qN>OB9IE#(IWc^Rjv0Oapq1lom7X-$L75c z!m+1d^b1JdGq_Tti1|0;t)>vcUq{QH40W<=ibq_}I(9}K)zw&EvC?~Elukz_9CW$w ztEW^px`z=ik}ca~wmUbk;h4D3mERL6YLL#0$_^fu#m&RV`+i`;`zZ_ozsr5G z$EPB4q^8Pq12lCrtktqqM(DR8N+O-Rf>fW^9apg0uMQlWlmil zUj{>-iL2(O&b+8)iZTK-IMR9_a99q9r(9$2GBY{zOwpjMnptLu#E(1w0QE+Kpq|FW zTI2fS{c$u9Hd&T6e3X;aBr4`a*vl5^0Qa_q+o&TL)x?xbOJ7q&DytQ37%|E&4aTj# z`il{@jy}lbuZoA7jFf03k~CIXg9bWVYu>=&o>KDEOh_m%Zk-7JxP7aklxdOW)@^mL z->%@_zkD*eg<*CTLTeiUb~nGb^T0_K+^fxHFTd%kxjtju9+p1);*=-IW|HNV?noE6 zd=DK%JEDLW+#a^SZ}!6RKmA4;l?nS|xjj%HL>%=b2^;{V+WT}pzg#y^acTW!y_0nf0oVFxs>%d?OPw@+^P$R0-cNAVZp zX}F3`Lvp`~xt$JBu$;^Gf07L#l(vmQ-Fo?QTGuB@#ey!nKngFbRhyS(00f?dU{0Wl1ZUa%`TQ0UV*Tqv*@uGf61jgk zDttdTCV28LbtNp7^KkP*f~GoTgYgX~=g`O^Qu>1%fIzvp#Qy-5e-2L={Nvz!ub5n~ zEtivtyDQDlK!BX;}JAtT;wXLxO!`&>?d^&s=Bl7#jhaE&0KA5j7GbW>+ z1$ybv{{S(O<1DRfDBjJhrSFQ+>vw^QIKQ+L>Eu2tT*_Q_^ADEXTgt9A;$B|y_YdZr zEyejoT$EXsU08u)q|ywbwT)*zk0#&vN203fsf01}@PDvn5J@bUc&c>v@<8^4bm)g1Hx z09Lqc-z~}Db3IFD4p{1%I!J=El5cf4H^YxUx%ENfPvTvXalT6xJr@SW$2>ieaOFBE z5y6wvS5rYspmYGDYX1Q6@v?T?uTR(Fgpx)UBXI|Ve-b=3&E6aE_nmTUjPky8=FJhI z;n``>Rn-YrMn+W(RIZq1CAC;+H?^@V;Xj8DjE+0vu4C{w2=XV7GyW#wTG(>_A)%&< z6E06vBxYFSmsE-_$Tf=+Ep74F*Ee(iT+hx5DPNoOQu`x#ACuj}dXl81ct1xOShI+#N+xp76YixuqF7Wi)a5 zEJn=4fPd{~#;!e9>Ma?^#=!XyR6V3FRp`79c%=UT-Q?snT#Du^bA~EoUp7kFewpB< z(hr>1Is{vfUcDrc0Vix(&SUbYm^`N9+}D7)nZr5P1#yi7i0d-!#+buXOvC~MDd}-y zEpS1&$4(S}BKZFR#;-bfw>t1+ClzO0Bf{LY;ob@2+Iouk>3GMCGH=?AB~1BcOISxz zmSAKgAKqMU!q_A6)TN?>#jgiROJDf9rscm5M?EC-EcuREBuP3Ne8y#F*HK~|z4yP| z*)lkg!ZTie@16b28di|SBrJ}yltK-KvH_? zKg7RI`{Bka$fFRLn^cF?cHDOZ0?w>vEZTK1@Q(igEG=kZ5j>BoLF-+t56cdX)UimU znO>SYiB?P4n=e&s_P^Tz$fP`=8`xgs+Wm1%6%O!58JMb{NZWI3bipWHklj&Ek+A3u z?TZ2GPyiIv53W;kFZRVisV7~dew}*#G3>7#o?@3JuVG>B{q(@nNe$7Cp)89dA?+3HM$YC$E$CqJc>tBBG5>^hsy$`O92x`id6bq;{O1l#FB~}sz}``s$K#l z1V{~<*4=%&?|d9rQeZlRA_+|V=Ni4Hj8l^(A*ea^||;+jxInh5j_BwM}ja&bSRh6+kQ!DY)dbVf7^&bN71z#IEqgTJ-# z+mup6_=Q0+kx3dk$QZY8Af#!HbOd)`|X+2w|_RV=;+r>kmqg{bw* z6Ual8`>iZaoAzU*3m@}i$zLzcW3PA%A1wLGk8l<3umb&hpP9fjpQptXnI&OWtVii}$Az-JD2%b+(rPcE6EP5UH>x?pCHIb4nTnTd;I3S!;!Bp)c1k&s* zz@Qq5Af3+k`Qh4xD9hodijJZUN<_|H%cx$>f6~LHv1jRcj;NzC4f%z%iv<8|E%q3e z((zOtY(7NQUTFhZakOBbgZ}G*zfHb)5c0FbAghBcanQ3+RMXK_lq{8D2_lWXC^}x`5dJZsOn!MAJO{T(2|K$5nsN<{ikt^7~+i%!AG5LmL>u zMk?0}^0NM>{qSy-atUR$r#W?EP^ALXL8fT$t-#V|xi;_9&6fCsDPi+fL79b5Sc3Pj)+b8VCZYkx6`JP~DZ)3TwSH+Yar1?_7Sr~+-Z zx_20n>VdJ|N|$BrG_?|nxW5V^rHvwe40OD=AZqS5BwwYmC66{r2Be*{7o%oDP8moJ z2(Tf}FCm`mO7f;!WhaiK!OA5?p(6cwXf;4WtQaIa1UZZ$Bd&ssfR4eYAW*DcbaOCOVu%E z(xq4ttN2Zb8|~j?jiP)Jaw<&AjCuK(W%K}|b52>-c`7aEXv<*vk?L!m`T%=@g}YJV zHPU$l@=k0!>7%J1HM4JrrG0jF;OCK9tWeCYH5GJjSlG9hn^&kLort&jcDO%GWsOQ@ zKZu*p%bU*BL;9Rt_d7MQgILqRj_mfenl>TkW-|BJa9dpa2bB9vB529|^+C2ineqAgxaF@iwnLiB; zH~!9L2T-}ve+9%B-`j80-yBl{A~L>PfOgyydk^==Wn7@A zSUGR;K&7TBGagiB4x;w!mgl<>dk=q}IJe~(Yv@i zbnm}0@?873js5lXSr^1IH1z9P6d+2PC1D=d2h;%eBWw?Ow|>B15$VH65DMg>TZ4OmM#LZ20zv9kph--TI;5`BJ?`3v%oFeQI4xNnSitMn z_O;0Q{IJ(GL@+wa;0Ue*DF(;d-#xJHmr9wcRnes*CW<@xg-B?fok15JK(X8Aaau>v zQX-{DtBN_r9Q6>>IgeOrECVi^h6A|Yr`Ov8$(iL4)YN6doaS}GB~dI#z^xe+^Sz~H`ogSx8DubHFCohmWo=1knpPBY?MznY7fzF{tIwJx=(SWl``D6#ViCg;7)`r>iTPZd5O z`N3C`R`VyD9BIaNIc%b?hDyrDB93rWi4YATUg)P+U4}9B>g#GVw9RScs?HPe&Siiy z`Tk%7*S&;hnU&tHxrorPX{wI2?)zvZ9#L>$Xk=MnnIDjn6@ zB$pK0tTrhYFOJEU9`r8c)P#3Ij5`Spw+?QNMldr{-~G(iY`ck}ysblZ3dpi?|;< zOz(tqy!VAO)u(bQ^6IHzkVb48&k+n$pf=lYmeMXE&8hPo^yfT9p7A#mRn^Pp)lVdC zB}0d}W_Myvut!3ATM*2%h$y&kD3>gwrlqUR>KTN!g)by2u@NWvP!WB)o8PV*WzH*3 z{&N;(8bXVMZiD%p4~kAyYyc@1a+xGhWU^&6`OEq8Ok{#eavGUcg@`vgfwLPM5pLjv zfisMLXt@jBRjJW9l8Q7$1G{8(hYyGD>d24ax(3_vkU~xtgtKmmxKC zG15;}u^lhmTWn-^bE6rlbgb~gZTfIOyISV^cBLZ`KXxc>l* zIjymk4k1(}^Q9t0029*J-vp`s;8IjIz$Vu=#SjIR8(>{8paHfjrb!Woy(M(@-r=o@ zBn2h7wCWHRxYK+7Z+r~QmZm07Cep}-Vm7Zx)wB08>w_`bwKEtOsHG;t6xJ$u;qSu1-^v@XlvjSCvOv#;OVlYJ9}fuuD8~d5(eH zi>LtDfJ>iBf<`DA7FSV7^wZ}Q6dAh19I??!1dTOTv8V;oHesi5dmD@N#9oOflJl8a zBSWRGI{S~c@J%c-ROV2DI84BQ(wfC2Q~>m4`4jr$SjP;dmV_aW5};Gmq-FOgPSzjz z?~fp^@rK*l+@*Gse!(3su&_ML< z&{&gv9_-q$Bx91fxm{*-ust1oQAX0Sf=P{*!pgx&wUk(${(bO;baZu8`E@NuUeiJ4 zw1Y&K2>lqJm4NTx0_D6zmrq{VW@}wPn-sca^Os7_6?BEU+h8mY$YF;$%^^ssA&bh6 zDs*Uk#kl-R7B(z99V7yKk%F2_77|)ICYIz6{#Yw8&Z_IGDk#!H6*#!Fu{v~(&HmVjaR(Dq@Mo7!(NxKr zPE+vI%Ng@3P5%HO9j|ar`UCXEcTOuR{XsR@7Dyz zawzJdQ&~kF3srs^Nu`k#Lm@*TNjLP32+ezR`(iTuzM8(TFoTJ+%Dm>CmMP$lC3<-2 zWO&0qsLLHiZcq|!ZSB4%R9OaHml|jyhBT&)bg3X0e(QF%&*moQ3S*q_a%_Y*3M(%& zI3zR0OEi@e$Wl1f=~_G7`bLts1HSv7rxI+cYAoWNglkDqk%P1>1Il(Kl$&0|dt2WU zFmkw9dGv9+kTkrJlG1$-wSmKKXF-xy36@%FSXt3*!s^I2+hKjhx_b`TH!jr}XQ=sRzRMThZpK6{u9x)B4Z1UVx11Z;M;5GX?K}}Or4KllF77^L4<(mRYzh0KNxfs38Ddw=QC*qQX!1dA9O5sF+nScNv zP};)Xdj9|+kD3RiqN|N<908Q8#@dzj0>Boxs4c+Txx_-UgEym=o=6%dhBYk9CVtyAbobixej|<26sbEo>0`qN*#j3CBk1|MTg}V9lgHz#{)@9?eK+sS%?0df*57; z%*!jnA4x~nFLphEv9+uL#`C@c96us(mx}HunhH-ME@{`)MgS#ZMatEciV!_^WGpS$ z-x@OEmdcYcqC*_bIH`zBBil?!WV_gnx7Y*p`*bt@AG#`fp9}slGX$cl%hFD4XQ)zn zeA!jMWm4)Tx>)KY0ni&<rtIy?W+8yLyG?JNsC6#r>B*q>4vR#=w?62*x^iRfdN*@VVjlFqbHjf@+=#%HD4> zMs|wP=^(Yn{(*Z7Z*G{%2ZM*HbipX6rf{ls77JiNBVv7sIO3YjNJpyf8fN0`W0#Exq^rr1iM9_rp$M zFX4(uJV>mri?H140_W|2>5sazOX2(?n6nmFn_2WSudD^?I^N^1*8MRO%x0b#>EVnM z6O(qe?0WvT#J0E}F=Hx?u>rx^#q2izxQ$fCCd{IOS7RAf1fjo{eb2V|tmlw2v5X+n zX!G+5s){VDEs~j(F_Er4E2Q6h-)^6C^~3B{QB%V`H?9hnI^~dDmveB}_t*?J@DxzZ zn^b0X5x7T{qL7x-Rg{wZ9gV_{p64FtHArjgrU0!lm4Yz<8)`P&^uW*})0|DxPD+NC zUzWNQSPxCQ?bF)~)3YRD!O|-BsbuhW_V6YlJl5&Bq1k%^B%w(mWCWbPT?m;%au=kxk3eZz= zB$XABl~}2~keY#$Q6!VpY)!|${qYTw2M+{C%UKm!H|jt={{WsPc`_w!K5s`|O$K5m zf#pbN&4;x1AB{i#Tfwxf+`Kdq|F6w9UVnH(a98nn^KO74UYc+TsO}W$q;WR z%sc-84{x2ZM-H;pWRil>J4I#v+kjb)&2jY|uuqw$ot%J8^xD=V5(%nI02LmmqC+aA zgb2VOSnhlO06aX=g9L;kjTX`Z^&9oWdMH|kFtY$nw3}V8?ta*O%VRY)kx~^1(vcV^ zu_nX%;MpA~xmdR6`Lo2$~Om>Yf0;nBH1zP^&5sH;FSJg`~ zR#B%y-|~;AwgkG(6vnq1Uqd3itsR}1i}l}EPxZDQX;`|wn${<;LB8EE(+NXU3$y9e z>JF2*7ykbMOm4=D;M>n0VR%mDr;4u+S+-lwYEC4`Bh9mp8lzQ*G|DPTkUCQW+A7r< zEK=(-n~g7tk<5;_n!GB-t|tpjjOvc^SzBVQ+Wo)R4YI^n_dtdF*pXxXF)`vk9nE-W zHm%6BjIy&S%_$^mO1gTO8Yv*C7Y!VU<5DoUMgWcR6P$x0YK#WGkJjD3ShmsfskzLV?wk20L{Z_QVznlLUZ2 z?;){k5N&&PAEqW;HJ`~vm{C0@s%nicf>dIxy40yVe2??`;I;r(0c+{l$f+li*RW#N z+z+o(J+R#}#`>AH77hCRh6tyslCV`5NghOIjkT!^rA4%n+olGJ#$;&&E0#WxHp5(S zpt6ot5wpe$*-2tYPMcz(Ci1v@C9m0DMsqj%ijI-J)O=gVZS} zsl|7Z)kE5Df<2O2NWUE`npvVMMd0%+dXuBSr+a*`esRQ!5z8RU;)gF$ZZ!EQ*&+p ze%8VmNj9C~k(6kPFZ!&E>wi%vbJM?mxRGVb09u%#n8#~+cDdWrw?W$YZ%P(u&}apj zfJ+M#+TVP2x$tQCTk>O!{5wbDKg8E6_-~onrxetFBZKn1gJNmAFs&WLLcdh(-W%N-gGsploZ9o%q{2(&z+UF4Z ziXYjzps$W(o|-jesT8wWT(XtAb|Bmn?{1?L-WH20HFVL`)tTdlpvv%>1?DHM?tdxR zTN27H0hO|f=-lPGg*qhF5t6K-(?|w32Ed)c_VoP5H&c;GVciv)uF52%%4ln<0<5vh zLaQy9$8n@G^#}8B+z+N7_*%YHm_zuX6C)dfZVL44_v?WQoZ7wM%yVk0oaC7nzs=NC z1-6qJZlH@;o|_C2mqkxYD$h=4bup?+t!BFQup{mB+XD-%DJ``&s;8l?HBBr_A`_`g zp(nP$->>`P1;k{~!nE{NPALh~Ed3CRHqB)%b6QEtlGW#PRzn08a~F{= z<(Mv(>$ta0mc!0tojcOf#MCsBv`{3|0JmaovMKFhruXT5Z{NdD!q<`<&-h#C{wO$t zr;2h8Z>C?wyj7NF(N??C)aCR~FOf|x6rZ{=$h5Mrn6_Y8I47a!BQ&fstItIYw9&~P zvA?Kl7b;DMy}sD3rPoI*oYr$`qMbA@WnWc%vWYV4?5XQvrdjA@0?2fYwGMzCn&QCq z7?wbsKABe$X8Epdo5P()m9;ino=P+=Iu%5Qt5Lefv1-uKi|YzDTaj=1XIl+cS4omb z1!Y!XJlVoi!qUj)7D;Rnb|Fu!?0^;^fox7vmK^6Rtcrxx#~Tkm{$;;72l$5K#{U3p zK1PGdR~8MZzHggk6)z@XLy-AZwG0+no?k>(3Ij(H+RVf=5_VE_sIa+t%Bre7`eZ9j zQ8Y*k8A!3W{l4RE@X49ww9wJ!3q?E?K$GQ4s8O7R7FS!@O@;P7_vx~HHRi}twpxi= zyUSqrHxlUsX1BG6Pi#z5P^FR^SAbS!PaLtxK@LGyn)X3*2>0whxObtMYF?l4@kuS? zBh0mmSpNVQwZ{AV;vtra-Ws~fgoy$Gs#I!TyYJYI@g`M@o}!7V%&=w_MjDWS{{Y9- z^%f(4Ve`X-g0HlPDQ68*$yuM$(!(V!lBO}{Sldpt7F!RIQ;PzU1<*s6QlR$RV18G(L5^^Eek$MFB1l$Ar;4hXLxLGxG>R7BbtcDd{SMgZ zo8a-ALBoFxKNPjo)Wc8z0P7EqDUx`JDr9&mqDB|7*p&z72^jf4*hEg8G;=NieP3kV zws#ZITFlQ08I=`Bgr5vKl0HR86;}gf%}XA+1V9>bvXU>PX=XPUxj4OF`Z#7+uC3x6 zs8mWzn;>9U_;)9Lt&2zDZlafn{5kk};vo$5w3F~YL}}@on5n0S@G&Wkm!M)-Q2+n| z9e2h@2Fri}so=O4=tkYUV~*9rq*JGx_#9tipczKd2csDx+8O(BKH3W_HvKe&hQfx1{`wrbPzfT*~*>t`Z zyk+LqF;%rnabE)E&!R%6HkTo+bdyQgsr3f8V}0$8f4n{CCZB=psiXpEo~Epzwa2bN z7#`yLeZcA8tM)oj{vQx;K}(kQvNFwV*ye3tQI}Itp`w~nS!DARvD0?bZ7e%&wa08m zGb+JRI>Av9V__Yd*1D0UfgAMN*l>E;CxTRUN`=-~hCi6v!+y6m>+UUxwPeyOOHmmS zKA-?&*n%t%xX0K7(R{3LJc?_~-|+QoEKRLPrr>m5hx*$N+^4MIxcQgD(ec$K8t{bG z@xfjv49FsP2*ySmfHiKzpcso)RFox|ntdRH?g2e*h^A_w(@pqy5z0}H;`cr7F-KV4 zz_cc{*|m|p$A^ZvbD3Px%Q$;4rK8BHGurA5yd;6+&={h&t-}Ti8&LlMQ;P*%JVI*f zd9D?}Dpz|lo7?YVFY~||9Xm^w!$LCx)u`p!T>6n12L$_qq%b}3g>5vD#OVkw!b85R zu{{r8*9nF)*u#90xLLH&T%?T~8BE%@P;Yg$?mhmP>T|%q!B>+M9IN496dozK;W?Yb zbs1Xc)Vw>wsU=Md(}nX&)X5k!)wY3VhBZ(KVd^6svzLnT)R@voW2CnIuhe5UydwNV zyi52q;tDF>Q}LZ+@Mx6DRl_-qjW$zS7=q=XC--t2{{YpDs}8%{3)Be-$3i?V@QYwXmr||&xJq7X47a#Gy zf5#j}m~kf&=b46mo=+f_TB@0zX;`1(XJSbL-^;c-i<_Ij46lpUS67vDTPC6KtKy~U zmKr?SXND7+RDblZVp%R{%?`-0Ikbn&a%AA zEz}{eqIo2ZSfl!p!$!fEanOb!-vgw3S~dZ+`5(`!L&L8N38#r_rt?|Jl-p5Wy>R1~ zpTSqfd$pR@76FMC-1Gq9m{d;#$|H4kuvR0!6_RNvSXb0FJvHFWnGcAZl67|AbGDF>Sj^YZ`$~2$tk>un>tCR6*W)z zhC-f_tVuWfllq(+EYTPyM~c#$*@5}refwZq`Wa4Za=xTk#YVQ>52&600G1qOtCE^u zGAPz(wTL3*?hj9$t%gV#3+uTqZf)4$iB{!Gsr7nJ`+#;hAmUJwoF#IKnHC-*lBBee zHDZv!-IYqQ7arqaK*BAeQ!CsCxUdG@@XL~BOu5$*($4lZ5Ui=G{W{aq#C+^j;l>(? zDV}>ga(V~^i`dwIOP|*Q)~67Pc#LwT<2qFCE=~Sh<2-yD{6aiScrD@;uH^R|O*aQf z>iLHYX8NjftjBwuP?P(o>uDk?-!sz~5dfN3T}~W;2>Y9F?~aDN4E!EBd&NAJ;g1*o zHu=Yu^1qO|g#=mVS(ath>rYddQ5%(dy0!#Bt_S@XLrHJqTiXYyd~Ib*ka1k^(v^D7 zIjxLvE^YAt0Qlo&Rk>#w^2dnzCF0_XE-zJ_WfaWvg;llMxlqAZ2Eh3hVPyirPkeLJ z@e%lWb34EXF|s}#;|?O>J~QEL^(UJl&GPwtx2=vMHHqlhnJJ_J#>BE6^s%u6a2)>l z&vIkKX8<>c--c%@xOam%ew9|3aV(j5h7i`VlAf8pbI5f60N0$G-u5`=@0+~k=4U+k z$28;aYVo%aaqkvXv1zMw8itYgJr?H3y|kzRVxJF!W;~II`ZVN^%iU!hqQ|PWVdskB zOmEvsZ}s-Wts>LX)Wsz3^A?dW8Vl=;{%afTM%EZ?m68#vI~fkdUgF(wRRn7wSsjYG zZAurfUc2_#<7Xiwnpk$wrqt9c4B5SGv$Y*GldO@KxHDadECId1(#n2z#8z45l2CzK zIFZXCw&dLJf4RcZJdve!O=e+JRUB7(Fv+E4Eh*LyumJ7ueXtcNQlrzWYwmg+WKJYy z0BI@7D$btrFad(D*X{oQ0HzzFm8Y#YEewHdEO$?z+uP@lB$ZjCDm=b`8+6~l-wM=B z(12B#k=Sl8+?#!{sR1VnI;J{0AU|$qjVPHa50;EBKPfuyzV|D+{{UP)WRRaMv~tf)A9rw0BOy3Q3`AYb1@b6E+?N3RHLn}2)b^Dw59Osh7PF$+0X+f}=5{+P;+Tlne*Rr^^*Mw+(i!jRDn2bnk$1O;EEQ=g_uAPgh_qKg_!tqdi z5cn<3xv!j7OT_%!qswys8Ovp_H*C|0B&JmJ=L2G@W16A=0L`M`#gEUsk2vd$Ig7-c zMaFzjnAYc+_GMK)b!Bw&nI){6M=Z}H9;A|QzSp)iJ)Pj&-{Q&1ryi%D!8=nZ0*5ri zn9m+%T|CrO)Y)W`utlXp$MUL+mOV)zoBNzh@>!*+rjCZbzcq()LAEL0F$MY*kPB4<#?s2j7}0D>OuY%w`&uB{9;2cb(uC$ z$u)gwijy#^YAD=*v{A}bvqk~BnF<#^`*gzubd65x)M|#G%MOefdau*&EJg-4R!|ok zQo8)gOUo5JZ6Ug`a(yFWEC%?4%`3}YB1um1NG?K)gRu6*p_WvRmZcf0V^U0-dIEoh zkGIy?hf}nPnmR_yTPaeYfwGW#4}Gul-wKj;@(AN)m2WZ%$CsITqR3_m1rnbr*nuI| zKX&H!U@j~zw*L3U{D{=kQpUxEZUJp8xIuDG{`j()fH_|=X{VVZqo&NDSfXIM_0ElO zn!kmt#`o+#Sh~~6G)|>GY57Kxus#0(m-^vab4Jtk3|{8+@qQwSss%`fKy{S>x|>{q zzh0Yre=N1|3*hgGd}{cL;QmfzQ_Gfc>Aq*g`J_ZY>};YZK~X5R{{Vd2))N4N?p-BkF7gpo zRYgM-4_7MEppeMup`4jkLUj|p&t36Lj&X-+VcgM^f#{<}7<;JnPrf3&HrMf|gDzlr zSmYH)3-Z8K@SJ=lk$xyjDDv77)^HGQ^H3lc#EF= zQN{eI;SYzuJ~B+!SXVXTSm`)#D21DPnwcsioroUM!%r-S*a7d4hu|Dec%~7v zA;e$ew%Vv#;bm|+msD0z)+E$&RmD1!qsn3!9-CXf=lXZXNpLQAEo~J$W)UKZVo@Lq z<&BgJu_Mw=hy)95iwBiu5N2kn!&SjLD3egI2JLQ#d-u0PzqT$uM@yM1M9}6!YIT8> zsX`f8DfE+mgM4*I8p_c*!;&VFt1%g$5K_e<{fRM0nwUSW11NQq<-Lc_+w{bXgA$gT zE0(CnjaKrsQ87CKdy)bAjsAFqWp%X2{{U7!O)QdB%JIV)59wIeFbLT0bqkC20Q+KH zMO`GO1$l(2pap)Kb`~~0zMniCZ5+@&P8EE#k$lN&DP!rWfKtb(TXnf4UlaWAi8F2} z%$G2!4Ody@($l<z6o-L%G`h_%l9Ul!(uTAFE9&ZTaw3fuvEZa&xhVocT1 zOo=3uwDqzG-~`=OLW6Qh@7MjXCA4iJ#ayh0w9(b&)5ft>yb~kC8pn4@5Qni#?|oWD z{{T_8H;M49&a#QV798}WWUiGf`K!igV~SwjM2Q?TDK7TBVWCY!t(d63*wHRYJkn;| zI$5d~Not~&Cx$ShQe;p=us*;6Yg_G&uY4vm?9!v*`_7mko}vtaIP;iuRm&R3BtmHD z5@@3fd)@RknR+rC?047koga-DB>husW5cyBW3kr@dj1!pOt-^thsqf#t0OURK0~NU zFp=(Z_({~(>vB!6we8y%x=g(#cacm)F(h1z;>CDMinBBD#mHR6Gihq_>W&G>Y9Lu- zi1~50T>}ff?sgjskUJBL&?+n7yg{l6Qf+2iTlB{Y*J4+D%I*4bY#!y!Pl<|*t1<9N z@e9l|IVt3)qT=pd&m0nv=o|J|lvCYFFDK8ZzWmg3YBg>e%hs3oNgtT4XF6S(>WOgtaS6$a|4#t<*M}H zIV_v7^H6}`5=j7%THfU2qxK2Kygj%2z+VU3Cj+Z-AFP#h>!%PtqL73HdQ=-RH$4xx z`(cKu4p8nW`mrnN-{WEYExI`ra zgZg9bTxeSO#zA(SyUC$Yc$;fAObmO&GVZpQYt$Rn}(6ZgTA%4Ch<^q7gT zVmh9^aMK`+OQ;=N+T8`d{jd@YT6tik&z9HA!#U}aO>IeNpk{N?H4=oLr+cs86MXVm zl6snob5A13gu4NKI<2twBG`jw)b#aoB&?;RMHcq3_P1T}RX$)rmnf`}+7u1tGgw>! za6Y52&lKA70+xh*QfZ8nBI_g4eZd{@-Xoe&e|M$H01IDM5Ng?GiDPHgC9Fv{+n~40 zY*f##P+QXDac!;o;9BeEi*4ao7Gn8(tdIv;(ZL!;j@#VgYsWm><}Wm0;XJ>OxTibf z>THWIIc8AVjZ4oZ6&aArPM%uo37s}A0L}h5t zL4Lpa#Q2sdC=8|Jv}cm)KYO1*) zl!PetGWu0mdPmHB_rft#g3&!sm}b%zMiyJJC%Ef ztLyo6zqa^JbLdwem)INJ_O=m=NVIGYn`zve*q-MUNmBasK&a}Y)JQic*blY|!iA)k z=F)WHK;*QV95EJUKG=I$ibClFi%YDjXZ+R%zcdeLR#^Qc_h?%}-SmGRYi^ zrGfd6d=WhFPVv-4l($QeSvDrex8D(5&pXWOa|g^T>z6i3t|XD9)hui}0q&tf_4dN` z4=pHw1wGSDsVogBCNr=g{$KBHv3j_>p8VS5z7yb{0^<&1aZeKPR}Il7S&-#b6;1eD zuAK=gkwz?{+KALaHn6>gv0>$s9V$Z>m9||!*Yv?!!^8_X2Hie*IHe;h9T!ymW!71k zvng#X427-p{+L116uPNW39%%9Pty(2)Eljl1&B5$rLaQI+KZ?xhSvoD06ZVkk3^F0 zfh>|l!bADdfU)UpIDP`6T10ASjWkUDS(!$y0@pu2fS;xqCM^I)G3#J;EGl%~=jZpq z6b7bhWonsRT(Kce#P4t9NX8kY`bv&-xy&yBOV_-JE_*Y9RI<3?mmcQ$ZakiSKHRiCbrBooe8ANr5G)i0v{WlRpqg5EbJTe$ zC4y0+O_*u1)UH2@`wMoy9w_RmYhi*)S-j#vE9xb0*QonogqE%!GKrK5c5+N)3wGT8 zgA8^2Kbi1kzqBKPB*`VyQ!Hl0N2o2HHXU{%;NUzg*i0Z1l`Iu97fOFM()T6!(Kc-#1<@&5ph4nuOAmHfltE*Rn7DadnA+PRig`I)rW0o@KxP4n(_nF{ig{`hsUs21G-O;PV#E*g50)9DsC9U?(?I2K>0@F2^uZA3 zHBkQM2xfu5gG8FN-(mskJMGw<3=w!^YXt=k4mm1eLFH7DUbEP?^2W=n%L4W!SZ#f- zKh1%&z94MBFRG53nxPfWm1O+OAsxZ!0S5hVZLrR2n^aKJLm{sNOTd>hGT)&2Y1Bw#6I7XGV#Y-V>PTNmH`}or zd;GBEwGzP?9-AX;Aao<^{Z$CNl(m9c+2<*xR^HtZ z19C?8CfIk$^N4c@ma3MeD_|_qvx8x9ZEz3L{{T!}G|MtMrK?=bS5?kqXd_rkT$UCD zTw37R@BaXcHJfnubHSC8RORa>PD5rB0S1?8F3dv4~FVE2bOshGewu=jam4aCa9H%nNv|93audt8UUiot8V8SzsoY(2;x%}T(@Gn zl0)ev4Uf3DOgy}(=xyhbve?$@2YM5zqda;(?TDcUkR4N%13zi{>8g28r9WHRkRh^nFvYsi_ z86M?hjcjD-0NZx|08e~HQ!=Wls;R4Gr&y-CAd!FRg(G2pjdRoV>5H$jXf1tKRHl-e zf`*QsBoeh*j?=VhV9$0SpLQ1>*A^RMb(OsYR7lGR5bqr9&8Jvv0uRVo;@;9m+KggU zXpW=1n=_jMVbg07_r#){O%!3IQxXIDG+ga}^dewchx3Z*rLE1Ff9rA}OBlSGSn zoLPzKa69+j{ZC9zGR*diDXb|M4&@n+VIz68&sdt8m;@?Fj`}qgvs~YNTS{7zh!EPQ zpgyRA5H$m1YxTI_Z_^L)PHJmJw8$lzVv#hGsL``r=@u5-uWS$-iUS?1wZpAb4snzu zl@dcy__%?Ubm&0x0#%owU~RSSy|%VCckpn^s`GD#XN)?Rs~Ks_^X_9;M3Nt7gQ$bh1C3R1v~f?w8C@&FuR$ejK$CS)H4keJmOt%{-25A8YpDJbem=9O zrjdAIYdMQiPZWn!%-^yZ93T5^tF^Y;*S+zq>gd`&Hn3et%sYkgMbd_KHc zUx(g7xbv7FcQABSdT(n(Jzg;WwrJ8tXK-1Ww+ zIb91-aDGDQSVt<)Bd8X$nVWm{BHjL&>wT6Z`!)~uHvR!~e$+JmGE#q-tGbcH7-Iy2ZtO(N(ucdSwSdPE=IILZYQM0N(e3EH1>U^UvFIN=PLlh3`Z4!_WhxRHB{;F^% z6>#=x!dyxF2C_t|K4BE|z{SzyELPxkAC%osL$(R0%(Gm!N$IF+sCLRM53-@DDHx=~s_X1@3KP zH4jhzaTTop0Mt2zbI}$w5&618t%b-WF!_(3Cd#6kHifM6GK-Gj_XpnyJZ0oobQkS! z_rqd~DciAV9Jef%mW(6J)ej1dB#r)q*luwD08AXnK{q$(SMrQDYAYbJvkTlC?~0{% zEoGC;W9_j9_`R_xxTCJcrD8#_KbLFaFnwCZ)Hh;D{&+$iLs=}Au-(0nOceq~@W>bk zCvZXB{V=98G=adLNk33>*0Pnkw{NZpR|3U@Fa&}C+XCxU*?|{OZPW~V=7DxrW?O;3 zZ?+}u+N57p^{GIW0)K=pyf2wRU2s3l3pvZAd%kp z{YD<^>XgS2aF-ej+&hzddt2#((l*l1se*&hAN22rQr=ze+RggkbB8#@nm>5#iiCb( zclv$swz%F_6qCZQ>Q*2H{c&9dbkx;!v+0I$6rxDukpro(nur^et_ZR*tIR@lz>B1P=Ea286usKX$N-pd)dVlGegu=`>~LsF1Q9ZG6OjkR5RTzv6&cn6bw;^zzIHJq{Kk1@HB zCo6hrTk4{{Y1o#ibQ4VP4)H zyg*RWv=8{1M+jG_5RY3HV-@uJ0~7xMZZWl~swZnm46fd@udCnO;l?L|hj>y7c&V~F z9G^3)%;T@k>Ql}!30RtVZongpY#1F@zeDxH5mY>ZDkGVl$D|9|`w`c_`rt&Sh`JfX zsZr&C+KJd(zixvDq*SLWoJTaU=IG!oO&!sr(B7>;>_cc8ZMY=gY(rUP0|oO*Ni1Gv zLdWH7NLvxVw*C6`!I8|&hU}U(Z*#Ce-SNK85Aa{`uCDO4lK7`?n&duaqo+l;w(*Vz_+4^uj<}z|?n6n(JkH7^=4T7>KQQ=} zCKPKXN5iz2dKQIBS!R(Wrb!vgE~at-7PdBaH=oH36{RGR3MBDH(MUlbF@D5%#G@dt zmYB6NfT=5LlrvjVQMLa7pXzbC4o!R^GJa)v(D4Z#(Wq=GQ(<(61X^GLx+2^!c9SHK*j_;+}8tmGzL;scso<>!t^lIMI;p5%Nz9}Vz= z=SHh8p{$lDYNw7kosp$TBx{l*8wI&G!$z(#%kk=$G-j=7?s_CYjhZ$pV2sGYP5%Il zFLDS5X=&o7jc5E4vpYua2-JF&8|m7>pOx@LQ#NEo zH1HNjy2&Q3Oi62!M?w4~{V@-S6NKR7)myx_qtB>HMa$)#%Ya(!^C+NOpO#V z$qA_vs*5tPBn#M!jm{hxIjaEwKmfm1lcHFqF#%Jg2R@)Q>9FZ@)BbTSrKXLiS*i@) zSd;fq%7(<08jBIoZ?Qk=ga--M(?MHRP#Qw$2}SgRZZ1@N*p8np4JUhS-hH_t=YLL;N8s9P*N)X^I)DBOa#osSRsi zsk)E0_}&l0t1zRb{{Rn{jJleGEHsSV(TjIb(cI`8+S?L4W9GYH!swXM)y)g&`#R7Z z_jv`lK1kGNbR3oB^&Mo^lqK;aNy0n_+y%$ zpD?S1hSCH1zg8d999vf3-XD7Fx-t8vpGCm`0K}7uvggdX$HLGy82h|j7{as6Ttj5vof^FNw=xdz9k-7t)`5+MvlhLllb`MUT0 zKTHl($st`Xpjh7Bv2T4giZ+r)Q42Uw&Q-t-uqUrhpQZzfV(TWc=>(E}x9^13OQXkq zUa#nX*A+EEnkKc2mN&N7#Tf@sp~BLlso7KjK(GpLz5ci*D_RMjV2F%5G3&Uo-`?16 zR#?Ayw<~50M^HcC2+2D;Xc3TaxCg&$92*(tgaA3E^&=lq8a}oo>5rt@)!$KDTjznz zQYZz1cDU+#555wdwUT0F{5uP39nJl*JdP7933q4~MGGa=o%jC#0JDW7{4r?!)D0oo zK^MbmRsgXGiZ|T)fbDVbiZwQ*w8Uu^x&AL}dttsg0*Vg~%6M|Dz^dttX;X4d&r9HC ztPV*xQK;J8hxdFnwM@#!AZ($6+rIdvr9}ab(p^QZaNzg9>47rZlHI(Nf?y;fVn|zc zz60|Ruu#MRIt|YF4d-iUc9ag6TMK`CVu%CUW+90!a#ZhcrW$44%|M8!7nO9hXjrX@ z)Zf$PkCl~T+Crw*BHMj1*$qf%mOFW(`C}3kmLuj*EV)2Dunp|p2>!S=Dm^P1c*+fd z9f|({#u&h{ttA?2Pn=3AWCu$V^}^BvBE6XTh;@0(ur6CyOHY_Yv)O6Oh@|x2 z(sm?Y?S$#2k@YH*9n`2>+?GG-wj{sF319^iOr*@|ZA4hx-{0?pgZapW24pwXFSy_S zFw;+0p~%zw+Ysdc0H@akB~qgjmp3NBovuEAd=B!2GWn-i;TO@Rfh(~;!f)@2>Vi?v z1al-z?|9oz`Ucjuz3+y_s3u=IiI4?17Pj{3Yy|R4Dk+fv0F>@`Bd7XdjGBf}fk!FA zSe0gtM4HuHg1+M!Wyqfwo+3OiQgJm0BDt%@JhY(>Q|8dobMOs7DyvYV*4^6i3S+D#rw`!Q=^()>@nc-ADe zwH_(?vpf>S@J^3i9*JXg(#n5#dk|QA{PBbI(>(INp&V}aV0)jx%=hbv@zAj-EU~*A zjjnXt{qKV5qLwGn(h$H0C;D5y_Z#8G%^ZSLnQ8VtGqi6sZ3Xw$_1hGQAc2@dtK?Zj z2J6t@f4&-|s;GJ6h{mzRqfuallVP_0-8RK>)Izb;%Y9B90tm6`^ZQ{8lANKIwm;5K z5uCNndGItAlO^D@RJoOVu$pNld652D48e4rBsnD9jB@=Br~TQe79d z(VjaH&HPuk-LJLqr)gRG{d%SDJc^R@4~c8|kB+$4iK=tT?kbwEHms|cGnf^ZGA}!~ z;#p7SX9P0?(399=Hy&gp^6HomF+&Y4w%c33zic;DRRsb~CNdYwARU-rul2x_)+a|gm{YZ!@-~Xamx(j zfhc%JeAV+AmoVXqO6k1mOlt4uNHr0rHT08VYvW&DO?^k3O$eUo%3XR~U$4&(&5&19 zP}5aJ(YnbYfFcrHn**q++yWSH(+uz$ML1fQA0^Od#INEd&u$O#1J6E0@IGR{xSz{*TV0b zW${H-6m0J>a2ZNz1P#rHOMLNcwt}m$U7)IS`pnv*WSU`3NEn5LI3yeVx7Z6`z3}di z)bupb!&LH35oxul05!$5{{SKP#8WPtFICLtuXmEP#-fx*r$R_tRPy3 zN_Ltynj-g%fwLPPr{#0E)7u#vjValiQgzNDn=YiKX}z%qzo?(`At6xph?&qCnDxnHF^|2mq3OK1G@nru1i4@f{W*o}aU4wZoB(X5qkbOn2Iv-FVbjGCUGX&0Svc#vN zqNJ())Jr5t7==+|=>8yV2|rwBKZCwKs*B)p;=6@mfzqm{h`5F%aSrktw1LCN9?hf} z&#c@7ZkS%TPA1vtLHH}WElG^f>p^s_%FZjG%sE-g?8FM_%=|Bu)B`jEN2m`+3+gO4 zGPS{DYh0e4uG(e`P@-yN$kGG(M74_>{nQ%+jBn&cBzZR}xoC4hV5B()S4B}Q(McJQ zEhIpcYuI$TJDVF~Usc2WH!Vbx#JP2HHHejJP>0*GJN&oy$DB1~!dH9B?^;O5gx_-D z*WwXb7In?uYtdF#(?c@xY;Xx(ZeS0V(J3Tf^4V^CZTjO!FW`C}UvQd9P$W}I?2V?^ z{p;*LTYi?s@%WC@QPOk2o^*^V1xn|#NedIX0)~syPhtyg{@BO9SuI6J0&s-S=Cb|+ zRDhFWL$aIw5B0}Z?5^+Z-8gshH{`j$Y0c{;{{V4Q+6e^V?!K_Zn;pvc`iyy2_hBP5 zG$Y(>ruZ_RKO%{qHMqW@E;@`f)YNHLP|GUZ6d-jw_U(=HBMd9&TmT3eUqr=Jl(Q4p zsrJG$yi+uV2qcmLA8x+g@lc4!uJRjPY<>5_Bm{y@EL`lQ4Z+|2u>SzAjwS%xDw=Z; z^8+@$!*A2)k0Xuh8Qn-yPLx#8SX4$)s3Dz*rH84j@t%!<3B$MI7yz(1wys(l0QuC^Xqh^gS)fEI_ckf3I9C9|TeH1r1GJUrA9WKhCUrFdqTsZgvh z>KDE}Iv6LJpx6s<*V}Kt2AB6OFzf3BUG$1)(g7#+U8`{|LNu>Hhsa=h`VuPqgCG&;Y`qZ8F++eoh zLq#uRcwT0igA%^4zs}vdV6}D89@;@~xE}aJFNP`Rf&vw1cG9|u(z|sw?T0!#dd1C! z114H>=>(C@Fbg|UMRg4_jYIc~uHg?-KDYo-JDQ?;ib$Y}5GfJL`KsiANxqYEdt0^~ zCd0`gH9`eQ4YQAQ$29N_^M{Td| zd{VQ+Q8ZOG6p_5^B0Dz0iC&jIZ`T0gRJDMFl)x;rh@}9l9ZCml^~ZRw8-}pn z*Z%r^@HJ?vrU_F>(pS-WgvyH-t~4h7JKFs|xN)eGo#TNi<&sHQ7rPB44%>F^`rw-> zL1DQFN#sV6WV#c%2K$};ztrxWSu0Q$NM-ytLaHZEelw+$3_5KY$nn)Y^YSL zsRg&g;*!3yNd)B{kNeOW*${QVR{9>;EgfvY5*FZseeJ#)Nqst0E3g&@{dT#+r)acH z+D}kHwZ2$eg_Op&6p8bEW8?weTPXc*0o;O)JkOerHzsrA*~Z zL>&2QZ?G0OHXC1Uu{ANQ3gx4XRz@tqTFl3(Bj?`?Z#2T{z)o2OeHLq9S4k~xE>Z@s zU2dr3iq|%Cq>*yEK(|&G+k9L)dWuZm2p=a%a~g(7mSC^>N0(xnf6aBhhsc4~7TP+) z8mx#$wqg$UKHYHbOIRq_&rKqxy-~9RaPs%!Ph8aSx_8y4V4AQ$!#WeK~C4yV7 z-=%>5cf)GVV`-L9bvp)E=olM|@7uNT=!;g8n!0HgrWg=PvC0+fKs#x%EVc{O_8qXj zWkoj-LtU95f;NF}&*lND?X+vqGYv$WZU7yy8}FYr0koQww6O;lC|rbF07Zv2K+LM3jUY9N-=XRSx?w!mipL66e$vUZ>Wt$y1!7pWGNs&TCD}+@UBR{Y z=xvJ+l(8+WzG~@k#SK+{X-h{z1EqA*tT9NlAUcR70@5&Eg2kAC0l!i(9e)wUfEIvlBt?n zS=`F{3#1@gz&Wypzj9AZI?{0lSymvV$*RQyy0n1psg238VRCu^J7O6ob3&lh$26%> zn+DXz_FI52*ROmy(9`5{$ZAN1VGR*4PR2GWr&fZ?x`ya&W7od;mpF<{b8Si}XyvPx zYIzyjt<)GJHah-y9c|Lxjs36+*G&^?F0UeuAl}8gZFA6d!Btb$E@zr%kU>uLWlJn_ z7ja6Zn1lrSn$}UMl5JvcZ-%C-g0@KwByANn^|CYTWe1?Yf4(icYZQ`Vyr)>D5m!6U z`LA~Z#=s8O`davOqpB4%1&%+%D;Dz05$h}3!>$+?{{WCT)(m6`6~@d5)9d`OPFq;i zGffM#O&L0(2Vs7jexm`pk(N_c$jc?Bma-`GDvE`rYhGymO&fN%%d!1%@|9^Aq*{4| zfkJ3qVVFns=m`S$ID*Amh4fU&o@uhHsTxJBPRHC6hgPbRk~N(~B9V`l83o8Erv0#! zE>c`;lDQl`Sk)PpT+|aKEo5PtJjNDc2_nbb>^-(Pm3VODI)wOd_=Cu6BF#+IHF>^f zm1`i0bjE=BjdS@oDqAWOb1yVM{Ep8C^fSK-Rv;dmC@^#j)fs8&t{Q-=2Iu zl~vHSWTLK^(@zsKER$L!eSxx*sCE_v>^H{8M$&gUc^{I--HP)cHQr|_BmJ?;-dyIH zbS(5|hw{ga#tUf=MFx^%ZI$d+MIC)y&pk&BubkGo6p6S3!2N6m{&=wbnv$1? zxo^vpm}QgFW^^1ql+j3$f@cgUpi;I3t%E7GhiqKb&a&r4dD^~Nh`TdVPj>m8_WE|m znC8?|$voGh^zj{nyqD+k@g1*{PZAvQFtX+plIK##7*zp~tsNhzj{Qp8t;Q|42hz6> z@PDo-KToa(f*9jh4KJ?uRsJP7s#Qfmv$5ZB zN4`F#?X~iyq?8n4UVx}xda{P5KzviUQnvSVXmr)%`z2Pi9*fX<9a>= zei^*A@g?CGnHYEyiboCegD$Mh-O=a^Gp=P#8~*^)m&=b&mMj>VJH@y;xL74N zv^6n~X#9%winR~tE;SZAfOqIexW&KA=&HDTGyDq699ewMq8TM}0AsNi+>WE~(;2zr zCYO-;H;8^>aQ^^@N?gw@B^fq+<{Bcx7rcS(UtT z<`g=rV-gzz2dLk*_S*XsinBJAmJP~BS|f^*2T&-w3LSDZhJ{L_as zZej42OCDlXYWQz2se(C!QrgbWh1@vZe8`9K92{T|XrPi>=Cmi~JcOaWwG}D`>@WQB zM3c6r9%zjQ$}iWpHeJn63VgBP{{V(xhL085RYrIJ0J?lt$NWLV`Hs4;GLmWvVKIou z6~A>Nm=ux^s4)a|#mV?ccn{^5jD9udzIoyUH{xy=gM0W2f_tbYv4PMIZs961A;g+nOw=H;H>wBc;0r0IEt8=8cE?2D4GUe!#WUkDOsa& zW3hhN$lLnmeFKMC$bvuEdK!UOw4!!tB-4HWX-(Fs$`{eM>Qy|wXSOSgY-wZS4aiOc@c#hf&%_rbxDrgpPG961*rv;W8#$h)D1Q$Gq%@YfKfI7!i}d!! zvPKW`t5LnD3lNrbQAZOhDhR^S1@&OunIAxkh--NH@{prP6-)O_EH^WXr}UL=6<$QSz@J-||p zmYk{LtjropJia;PsaP7KQiF7jSwl9i)-I>?!LnuVOIw;&OEgtEtwZXls7Uk%V0Y4^ zWgYGJ!1*dkMVZtq7@ni>DA%ZrkC7@Xz3n89ct`moT}-#d+@v zWXCn8;I0UkmZmrsvxw%Wl5gJYQ|88_$x{&PsrTCmjpHQpSu3`R3rkT{q)!f{_5N!P z_w9uiQdEKq1|+E`@}2(xyJKeDr0`F|nV*Euh$lArom0iRCpEc4Ta)FKxotZIru<}; zZ%ROUpj_VK_LJfD;YJ@Aekiz0lsUd_SHnC4l(~j`#W|cr2Fmh^NKBJT z8No$j-b_HY-@GLB#kY;1lhg9FhPx{bC9Ks2BtB%Qz_UBC^xWFk{Xd>PrJqAAs;Fbt zxjUAz+-_9%gug@YkDon&8aGggCz@;oAJSnG{J%nYpc~jutd((MImz zOtONck3%UNf)c_oeCzMznZGnvi(sw;$|~9!M%G(`5Bg%f%glNY#mSmf{t+CsajCMv z@3ZvVaxK$){PEGBiQj_HExC2#Q^Aidxl6>{z^>(o9Ou=!9~IW-6>-#5W#592@%1vr zC`DMop^l=!gJ(sU@bBqlQ!m zx;$aghqx;D{{Y4V2Asmr1!7ml60A=+EoWhHSnC%bLysyeorj$alC^-2?!}6M_4!+2 zu(h#ZSwJw9)bZ3oqGWNPum`c;*pbH~u3b;$yfTGA9g(&UdW-&-#3>)~Qmr&zSd@@1 z+XiB7`g`JAnp&QYj6l$-4A8i1D(rgg+po_8$CjH2+&6MS&BW1VnR(Or&2@DG18D84 zF6CICR?E|G=Y*)_lBE)-GFO(eQ|2+fi;IA|m-49qF2lGd5h=Ku8lEGMhp8tu@KHjO znHn2~kOH2cU=~iNazN-tH)rsh@F~gf6`7|rc(25sYoBoc04Q=+$~bC*dJNFey>}4i zwIVuLywIe+l(PuO=4qq7h43$&QG5C$d^8rMfn;#X;UxUX!Mc8!u6lZD?HtRg*7n=- zpL}g|lzswuP||!)avpC~aU~xcaz}+KD>8{FY6LL7Y&DfJhp0_Iy^Z3hiNag}BqsO9 zEch+(q~zxzC@S*`Ot(7C9!&nWm<4>ZC#HTIMWfv83wReWzVbalOc}{NyY%=B*G*3fUB*AMIKPlO2D8Ta-E#=6&ZV9@4`}lGA zGmpbBj1Fk{cj8YJyeG^KPsJ>izx#`o2y)EwXx>Q7G;=f&nZ%w`Xp$y2CM&5DUtaQx^PGmonwXQXN4^zMChg!+PzP`Eg^#lD)3?(PIYnHHrO{@jTIKr+&XLWJ%FO0H`&Kf$p znw;KQz+xS#T)bL}t-}W)NZ-?94le2S8%YDm{F9)Mm3fbv@7tHu*|dBMz_gQRIc+Tx zWjSjJe6p5w&k&ExouOLjsW0!AvER@ zki0zal3 zz93Ui2aB$BelDn2%y^eEStkA?rC}S}xfb8v_+Nr#nfOzNMNDzVT7nDc*j%qs?excO z?7P2%h#%!2CChtAPtqPeO1Pp|f)y53)9EbVPT$W1RY(Fx$ITFe1NJMFSfF%K>6a;Q`OB^kz`7~a#Jh->SKG6b>H;H_Wl-M5B@{=#PGx7hdkyS8J!n4 zC^I;+ehbXvuaXs_t(Pm3Xq3VZiSIH;bYZJWYhjQY7NS=QR(r=^#QU7Q?B>TjvTjuK zSB!Fh4|(-NMVIAI7^IL89c8a2(C8qb;mhp5yRpVN*Q>A zCGztrKMzYlGdQUrf=X}7+Q6BMk$W()+iBds4gMH>hT|Su_)75`Sg6B;2VrtepYzk@cqc%b^J+qpO=}38bQGP z&Ebs7mx8B?nW2*`%qN-Z6U~nIj3l)a>2ZA`-Ht9tD?A4HPvkc){AF=pjLsY82N=!E z9%R#SY*joznMp`0>FObYp_o$!3SErx$)J)3rcLZIAmRT2hL?rTFY!I#k38juXUDu} z;WL}rHhr4Y(B@U`24R*}W%SJNPHGm?Xat6{U5A$FO9Bot%r#%HG{~fF@?7g?H3C^4 zX7d?X4Msvu&4;Svxi>e!GRlufn24cx;xzLD#qV>V_xIZywfKklZSeib{!7zT@Lz+k z5uAbIsd$b&wv&kXmopVPc4rECy5UI7?#g6E5+i8@1>deTZ=6+6m*iDdWGk4Xlgm~D z!N{@t{$u)Lgsj?fwh&W=gtQ!AnCDq`TFnGmTtbGORVfabnUNMRFevCGK`v5X+dgWR>8k@tEk@{zB0ZGc^TlFi@Y>&$0Oj)22Y&u zJJ)7;g-&4APo34pR3iLf+^QK-mGsAC-(l~iEoBiM*fIRX9`?Wc;17kg7V`d;@=)0A zbmPSz7*0@Ccz@?FFDPj^vbT)tIk8tK4^|}xjeG}HpU0ZbOeG{VGHFSpF&&9yJKGwC z@#W8c3Gpf8GoKvr<-}Q}90|nv^4Cx;bRJbgMfiAQ{p5ExVq#-!o}(Bdl1L<378x}a z1*|#)hfJKL*`*>02vFd$dj(K0sGIC8E`HctlDC)%u|Y*6M^e+}u&o7A-_bM?sEuO) z?Xfo|;QpO$k7`<2Nm_`A1Zq?MTs6!pB6^A_;3A4CxPA*LsSs%0#yiF3Fe2;779 zz$sFw1T4()eqsUG{Kx71uw;|Y)U_1QR1|@bYd`_G2cW-9FrQ^CH8t=~YLe6Dkx40% zQCxh+1ZrgL3H;W#zB)eTpT%pGJ`}t%_)6rDBRN09{Nc=adLhM}U0KCcQ`5~s#Rj9y zd9wciEw_(V$qgxCv z(87T)s35;X+W3g)XaT2^$sq@t>IX9Mx$x!Y4uA0<;La)LM>Y5plw9wt;hg>ojJJl1 z)zQ~MObv8;9a&KRA{g8=4K5{+iyiT1c?;rWzz2Yi8u3ZQejf9#DDgMOTw#;sygQWT zd~K061QmH>nNDd1M34nT6Bl1d7hsB{k$iLKmPb^Ak2P3jnLOo1EWp|Nj=crPQZ2W( zGb_VK4d&h`dAGt`kIZwLDjBP3b0?QDK2m-J!iIfX&6I+%6##z|F2n*bFV-+OX!QH5 z@>w2`THkLjJ|=z_`HA8mz>kQ0>xQ#VT=Of3cuR|Uf1mL7OOw>qQ^P|gDz;X%b1}S; zFOw)Bolz@2?5liXE_LxWpTtLk&Uo^l#b+@%i;p?EPsiLh#JmMlQI;#aP*c?`l~6R% zs-oH!BIl-4#^4ck+&IV}EO-WZs)bmGB!c%Dg z(6h#}56$KQpsRXxi&r%)aw1bq;B{Nx>$S9#Z*YEC4J?40E#+Tvzt^ICnn6~&uIAUq zgOK@-PvgTX;K_6B;;TG{DvnRp)n#QKing;Nk1Nbs*~w~MHfa=}&Kbvj^!4!`@iEH} z6P_h%%&2)Jf+VT0JCeNhF>AOQik&SdC<|O(iWwRaM9037s4$^$k|HZMXT` z1{p;`@|n++jKw`x7dF1bsWt=b1_Zu}TVo{UNHXEY{gp>Z_;?fVa$bIDRhz z*CN%{QpU+Dof0>tfI7EeHrx%Zz3~d7u6Qfy-~jpI)kjOF;`RsSeg1fK&ErW0Lo&-W zjMr-ct4;cVI_wAOhm(s4=w1{LhGVB}`-)^rxn>N|9c%zP8ts33-rHk*{vW<594Fx~ z!apcEG0A>XaAzKK0kf>niMZ}=Gs^tx8M7}r4GEzOCZb}FIIS@NsgBA4H^zlhrjswu z>uIB{f~KZuOK9?fJVhHx?REu9o$f)tH(l_W@Ndem70u!+i1~}dTxrd`+k!F*EW;(` z{{RnXF=ch!Sv^FuqcEtDu9b*J1%Xgq#n0shF$RHha{Ye1k?ILNmdq)>AiocuWpj7M z*Awxseay}W;C^%R%ZK=Di9cs#MoQW&<{!jISt171r987urc$h|LAv$DhU9mNzlPU< zUMJ^|H@qe3N%F-Z20(0eZ`jSeQ}`YDXY#*_JUMcQfvJ2{QuAAx$-+6tMN?Uy zM^i%8T?axPIx%Y^B!Q*a)*TS&LytO zW`j0Q+Bc%7qIg8pls;h9SjD{~PznvNxWNvTH^d;|SiX2SkF=)=3BuTBQSpiJ(~$9p zHx`yoAmVNwUS9CMUjnsOPX7S>4l~Pg%8E;9b9e{u;bAxce&vPzLi%&@wc;Owd_n&J z_^@UiC!6QlrDqFrvnAn->8oiCIgd1gS9*egljcOu_XoYsGuy-e0K?nC-fQ8jz_&2@ zrNN#oc*BnQy99|*SHTsFB?d(>tT3#T#2{}b9WNVQnA^*co7jwM55(UpDSSP6ljlbw z=s1!-D9SijiE6S~^F0AtvKZNPw2HR^Ko~0p*fO_l0~-u(J`nv3D3q5QD;puChLb+c z>8af+lg`wR(G(?^l0a4@-AMxd`r8uBzEtuJPngrP>`k{87dPqC{V>ENl3#8t@!FvLJXRYxOp(2edC7BUMfXQ=hV*A*B zpRd;sG!?BpZz*s7I(krBa<;G*>Hh$ehDRtRB(XYbjo_*oiKmW8U~9?clvAZ$+Tec) z1cUGQ#tw2qx`sYjab&CL5VsYx?B3fSYOru<85jij0|WD8<6pHiQZ zzhiNHyB&`s@>@L|CuqMh^IxD>FLO$Y9t_AJe6n_cWptV+j%%SGhm6?ozSh{``Ljww ze|J$!67TKE?nPi!( zvsY$2pDj)MUu$E_5^4jSSE1sBhK0Z{#3iMu@qf@rz%j$Q^y~ z`@;bt;SLQ@qBN5&r;$Ejiwk`AClOB_bxyu4xzU=`!jnXJhc~*qSZWgm^xwX~{+N{T z%8|nSGj)km@D$oYTmMJjLQ{{Rw$Yg`_q>y5p5Eb;ro-WL2d zabGW~a{TD?C;tF;ct@C-bkM{aDXDV#BNY^-t~5KuvV|vO<`8kIZ2R$9jU_dGJdjh@ zLN29Gs2%rf@6eEM)M1*BF^0Mpl2?W@jr-qqBHagYf8PTHyMDGpuK0tp7fc>0J}kV6 z=BF?GZt}O6c~=*3-v@DD3vlj5z!9|=g(#<{ta`e(mOGIVX(w_8ik%kkfzOSvhZjCL zyOiEAJVNltG%}wPTr-yCl=+_zW$4o6+(lhNPvPoQNH*Wp12TX@hSV1L=EdY#Y(9Pr?u8JrR0CZCzy zFHg*VW6*KcI`G6nrHY=K2%?G;F!culoi%Oh2X2@({wQ7+_&3Dwf;wJM@P8Tb$Aw-} z7UI8ZcVs4diZ^6?qq*PFbpmYbAZ!vU)cmoWL84X6e_Y@+*ovLkl#UsYO??XQd1aY z%^VP;P##&aH-FOKd{dNC`c`S9G6x>Db~kHU?b81MUwl2wBQB=7wZHuzmJzF{6$|)jqm9%)y}$%Fu|50#xJ9N-1X-0WU;*o4 zio=>qD(tVLS!H)^D=UJ3Huo0Z-)wnNIe}eDDU9h-3ALKz{jh;@r5I{2zTo!0Je7=* zIk}V;-+kNrwj9Q%ctD##Q_CF`^-E9XQ&mu9^pe#BF_{5Ln!rn9Mc2LTE_N6PxU{Ag z1WL{-7&AB$j<+@gg;Ns31;@|%OC;eXu@eWhOlyv-@rH*+iDx;}bnK~=jk z7>!a$l@*lql}!aFn(P(jYcE25Un`4Y#)?6eW*@exYN{d3zX=$qf>yfCCD&9#O|Kav zWoy_0dz?wWMPpk=(G?ZY#?#Z%$5gZ{>4~IpUNj$&vG=eS?S`kRnxZv~v)CJuIv(9W zOnMBplQgm_#|nmfU-(J(!15Q0LFGh3tAa(ge~|vTCN{YtEwWKYIK(i>Jo6EK8j7B_ z+yn2^`C&(bQwXUDRybG|zQEr07yBR60>?a(%xM-!XzpC6@Qd|7Bhw4C(|L7N>gv?& zQdt(;0JjUhw*1EiO^v8o&Xj*RuBpoNDh%oxby{8Gt8_!=6lNZxZ~0W)r?JH0z-eP? zB~?~cV#BaK_x8gp&m{Rf<#NSMBoiw_SfJDv_x}L=g~9EAo&w1x%<1XM)&3Q!Vkr_% zyB9aMmj|nEyX|~dF_4@>yId;SkvY9iS@aC->_yLh*hqlgquqtn2Z=uq+}Yv2M01Cf zUJ-ImMDRa`o*bc(xQ4ZOx+!zcE>wh1GfyE)%c&AF(P}=lD|=aS&1GDG)GLOG!|q5I z`k$uwYHa5=iWbV-F{?<(+A%9Aw_WUa@9%*jp3!L`8OYF{t7_Y9T4O^(5=wfQgA&ZL zMk8gq?|XyO0@UV_<njPr_GdH9ov^9;f1O4QE`MG*oDb~?5? z+WJ82uD>6=?C_P%URm(fKP5T&<6E4ZaZQ{{B-FgntxB32T1hD$H+pevti}A5xc(h? z#+RwHHMP#DjjS8|!{yW451+K74Q6|6qSm)>afUJMY24q}U&N}<)0rRZu3CBO#cWSg26q*A07Zjf-aA5f6t41M_>H z{x*3pN8%fZJW=uQ4dyvt{+i9Hp^GNTt1BXfCzQ?xq6gvPI~N2iX#-!Umw4;rQ>kKk zx_Wwa?r?N^8Sm#2*x%VDN8*4+p%B z@ZHR=Y4WFwcsD4_a=tS(Q>8sVY9y#HO3_GlG>WS76SC`Aq?ANrj36jZutx2Ewmq=KYU66i%&X*V4(7t(-urz20MiaM(#G@0IIxV$NF|M* z(oK(ExUn4u(yg>!6uO?FqDYLTq>Ts+y-I+j18(PG^!i}xxatd5{pxCiiVCWS(^$EZ6Lx*mmfd*di` zTB#c<&Odgw4s!avD$A&k+`sllF%!Z^7G@c5E;;p;%bP<-l~mGG)GRVF4J}gDM$MoS zcM&PS$o#QSRjJzQ^gkuI;p{FOPnccDa{mA?prYZNl2{(HJjNPW3kc-5ltf4@7&hzx zJ9ow0YKh~}kX2Pr5LMFU$E#uP__O>pC#R#y>6R*Gt^6%JM$Qe15h>C0xHbpniL_a^ zd=LtxsA>1qScN~Ow#SkDatRC4al!*a;Ty;Obh3D#=MuUn;r{^j9(LiC!M*BiZaZ{e zt}bT_)3iJV$FEzls}3dbVjhv96z`7r4Hl~E$dhk1-1iC zfcky!XAc&eBFH@BE3l%1<;}|vEq(t0y|L*2%fEJ=gZ(4qxQ}Vb@!sE3oMdU2PA zx3N2Yup+2HSVGScI+2aGzt0XeO6&XugLF6Cn_mJts1ZHF3jw*cyJP6x8MX3un3g6J z0p?g1EW~v0YhgxIibC2#r(iY&^*6%x5GxdwRkZYT)8*F)%`9vCvu{fGzW)GE_r#j2 zD*!@Fpu{8q7P(`$<_6aP0L~aH^7WJd0Fh2iZV0*QYkz;w5=H+2>Zn$9xA1|s!=Tmc0an$f#)b0$Mf}3QpD^e0xioMA3$pWDH{xsAFTK zb_bz5AJY%wVvMC=S8H2-zgzalt5(;F(W+lMdKf1SD{{X+XDXSGSz$Jx*5bTT#4Oiaw_ZtjI>54@qK$#*XtlKTg79gAT=)_wd zNd!JyM5vLdyAaEJ3wG~(II_*44y7H-sN$xPWQaBBx?ehIFlOr;_Tz z(MclB6Afjgwa7g`y|ATJk!CqarK*loS52tW%NS9nR77 z3643eV}L?7ZA}a(%#h6P1E|yL0k^w$9dKNgHAXmEmXYbnEn@0yPT*sOalNStvkeN6uhH`f>oiDG_9Jcm2?*| zu`%@_ZP%^E{`gW^wX;baVk55hRwVszhQlHmWMq)54(8kZ!NE`-y2)78PpbCZ^}Y+me@vWnwSxz)#bp%F^x$fTW#z+^xp#4xn*@msc0!>j2#iNKmE~H>`EIoi$ zQ4)iMRZy~d0!pavb$NcUK?2|(dyC=Xs$|Nlp@qEJreqRo2z0^@ zA>4vWA^sD6jfYc%yvmko8cX@QNG!M1LF#^ZT!eH|2q6^?VFd3K5C>W~WLNM>R-23#yBUei@RLxMUEV{s5LvPBUSbYE< z{`hdGt}($RGwNW@Bw`%-h{_J&_Wa#Di+f=KrtG350YQ6MnQZxtCW)r6%hEXR(|Syf z7Vb9bxwqS<2yz~!7G+ge(yMczsQ10CVS!qzO>qW{Dw3_~8c5sU1O|nDOzk-;P^&KH z_0zvlk{d>m6z%2|w~WSUltGZuLlx#$ne+XqwTPZyaBxLEaXsNKF+J-7G6Bnc$u zDtd4lStJptZ}SsiN6&l_nO1rAPSBTSRaGp&T$NA@8+9hv!AmvZB{}tk>MCS%wE_fD zatvXK3J+`hVz_5%trFTuh+SxZEQ@;p+l@nW{hTt!`h;Q8mM)r3`iSmvb@@lj`u=Hi zAD2A3%Oa|5&xtsbE#dlc8eM^@sfrtqr<;G*2GL@QfhlfPr>V#)vbTb4x~@sGskJpa z$fo5(GP4tInuV+|Oi@(D6i+2Ivn!^?HMqUV3VVxKo$Zd3xxMgp7 z9}QI;E12;|7-yN5V-(Y6kkDrG*`2h7BKF0wSF3sE#;kICCV5U)nWMqah+@o}I!-#Hd$L6!%=UONb+hoXu?M4Nd(+~zx-j5hT4bO zUT4)&L6dO{kk1rZU0aq7q_7aZ#q4ZsdXAR9_`x3z+(k)A!<@j&#VS+&DW>)BbsFFy zEH)y`dwcJU;?B~lqaflcOumMzFsqj;tqBBimU&z7@3JVp&e!jJYvaS>nu({RRzn2& zoi!;1)D(FqL|)w*$JO)$e0=X5oUr4_uc6?P5`NIT^x>)UspzR2QHp zt-IJ_bd`KG>KkLNn>KF?raM&(mk*3-wH`n9W(``c3nggE$w@oU~0P<9J&DH zT?6&$?T@`QSH%k%K}_t?JP)Clro&_H$s&mE{dPTm zd-lRDGB1%BQox&#Epm6ZD!G|Z2ULr^sUncXAUlig^V|FBgqV;QR+Med-q*!XFRZev zh{b^P={6&+uh+H*cadxvP_^%*_V*Zgs#xP{rr%KxraOz+^ulNarbP-%DA?)*kLR`( zk3tZN3#mPkOJGv~3+yTGlz3uP58BZBnkvcDn#N zn_B+>KG;fiV+G{PE#2vA&mN(myG^w(ax9CE^jPkk$skorv#+#}#EuU*xL= z{b5wP-q#&^VFW`Pl}0F8eODNvrSkSgv#`HjgSH1UPJG3EL=$3rVg$E^WseDF2-j4O z+iENaMeFmzPO=FseK9iv4#L}8p!(qwRlPxq01b*;ug~8f8Cr5A*<7u(1-_wf->xNt z8ABlhlAy?^TarR8lyB5@Jw9Uy>(s%cU^m&V(ERYAjwU2XqB%+3RCL?>{V*GA3>j6T z3c8Ngz9h&F0$W?uuUbhIwb+SEl7H^Ky5d`yWT_rQLz+jIRlve1jE=JEie)9#xggvz zZ8u)ud_w@2P}iw1xGlB+0KKs37H?Be6q$2K!!DJ>%L<)|+k1V7>4cVbDeZ(2X{}|s zvoj4>+zT-IVy2Nwxr}-)H7Omp7Y7tEUCFucb?f}_qDCgvz><1cEv@&!wF9F83S((k zNCkA?@BFY})h#MVB}x(gp z2*hQ2k!g6f5vO*sB#Ym->xGzUjOcN7QF2$V-G{ycGrYxs*%su2cL$~xGpsSBilxs$ z7~Bu^!!T0b(v*!BMn-?juS+{HQFGe_#-X(c*s>BX0^Z+Gaq_@YPISa!RZEgi+v>fD z`3<^YqW=K95r?~9x6caQno+k1!xD(KDT+7Jw;=8}*qdX-Y2;OyA$GY3)ztfe+x{>V zXu+EPt%0%ISI_!j+IJxt3xy#Khq1RzK?cyaG~*L_3mno}n|&ju_UL!pVlZiG8_SXx z(5?J^3op|RPfSE{vbd4R7PY~-7qJHm7b&xZib3+d$8v3gaVerYP9|A`d2Uy57f|0& z`H!XWSe_+u8wTH~klz(Qcc>|+Ff3BUJjeG`U~;_40VJ0I_Jh_Fsp z1By~M{5=Fuc7~%fb!8r6Tman<+ju)fzj;x?!x7ElVSTpM*!-+V3VU>wK`F2_n9 zfNXDnx3()oTCGz9rAIto&f&4OXR~~R*8CFqb{BxLbFCJFG1O|NX zFOM~?%`)7&2Lu*@YO3LuReLSq00LN?1IjOn2ZPG4K4))j{x3_#*e5@f} zWFU;K!FY-Bf8lQ}@RgqUSn!F#{MO2Ho-^V~UMk}p&xEN0mt#i~!NADlVce zWWTALk*M^RODM4h#0J%SeY;>d?$75Im0tZdblTftSmaZy&$$XWB=oWFKG>%6d4%@1 zo3twF)g`DR85Fc&EU(h$_cj*8?xtvs?#BHIBIBmOY;g$7Ws$3=sIY1>q)6A;1AAN! z{{SpX;hj~rvbbvpvfOS(t^;j-@V3Y=DJ~dJD9GMie!T=6f^UK$pF#5Aca4i!8~%p< z@ZKbMjI%NaUGH#Du)>O@%<9%)2(jMdy@nds3-PA&TQr>mGa|> z>ne~*Ot6=bX*z^qS+$Z4!s$QtKK}r3jO~83Lj;nz@@ZdR*qlL zB)zpN_99>#6vQkzD7bqG)MnrmErE*I3I4rG>u{0VHe*Nv0Rr zdU36eL}yg>S#54pEUXzyO$ssS8)hFeSSk149Y}mexgjTr9||1N;cT}rlCO;N=vRnx z1XVhkvXmDwkN*I<37#|WsAG?QN@rr5Jj-NysS-U>#VVA&p)2WY``oW?*T-}2n~I4v z#t>|<{l#+L@OW`!yih)}&zW>yL}U*k78f1;zor|*PGMM_yo{}|bI^DGm|s&(1ak_J zGKB?=#gz90Ve-K8vW4??Bdx~3?l0dRq|9#%kT~TFc7PDRraO6H^#1^i3p(mB*a)09 zl9t$>ml!>Y#)joI+Sj-&Zae<~JOL}oQxS{IA+=ogus+ypU(q$dZNhKYVqVuI?lpgR z!VWbo-e6xc;f=+tErQv6qNF0psCr4?ar43zo|cqI0!emtvFpNO`(P$58~K5VU`mkP2KKr8V3lap%)VO%x!V0k=HEWpMnmO1vzYb*`hEI! z{d!{`Cf3kPk}E<^9W}DXAvfCBwhC2wV@F1200ks_{O~l>JflNt3{LE~1La}Y^~KGL zlDyu2S+_aj<-Z%ZDU9ZvaS+Sp{hTFPe4>V+4FQAtEPL&MW6Oeuwz;cjEX|?6IXx|X z{$yb%X*Wp_$8Z20NFd_v({dl2`JXK7Imt`P?meyLEE7FE{6iL6?U%zMI7e2TdPbLY zQ}bXi?e0a%u5NK30r5XI_;;1OZ=G_}BWFzKKc~y2l7lW}BUqMjG@$|0>8M}>2(-ZF z^H!N@ni(N216`L|+*?}T^8w$!{^0#EjKMb{!I7+e*jwe>7aNLm?jL-khq5jk%VwpD zjao^jsB-ffnE=+I@A*9=YXNW#uX1hFkTQv6aUdm&4Z2?ok8%3Qs2re+L>xpzu_Uv5 zkDv3su!f|Bg_lCyfpfocxcxA9mkd#fSww{0Ks~+ga1}&BQ61JmNVvNj1Mk=AiFnQw zvbiMXmH>#wfpfU}->LrlU|8PlBNu5#`-^^D&yCocV=8Bnu2 z!ib5kX$fFFwL!UJbl7*e`CuIL$fmcIsD`FX5RAm1{{Tnpd?X#3F{!+wb_a2DjN_^J zcKFk*;pzCRDe%+IYW^RFnADkDCMzLPzR;HQ3DQBZTlMy~Ft(xArnORs}NH+ydh$7vwf+qwHnWSM-kij$}7^SsiIAW*xwzl5DZGq|?R(6Ut z1|$V^>FRd5BMQ*Gxn)P02Ay)MD8-RYjzW9NC zP_^RH5mm`g9Et*zV1X^OL_xjoe@q&4Dv6>offGY@+yE_af0eMyBylZeTq?7yeql{d zWgr7%aqqVHRwR^4!9uJ(KBnK-4sDS^Gk#Gr&v78K6L3w3YySY_6iC8m2cT8d#d_{- zVcQfu4EB*$R2E|DuRvH)*$ZkO8y z7@2yYx{?AFAm8Wubj9|I!pDe+c)x^r4zH1%)1%{z@{&x$Cd!{AoK|L3iG6d!30+ST z^)5E=i;EwCFB(qGAO8T07eAy>ZE?c2RvX&)xBTFug~ilRnOZrlLJ|=pumMqTwynVX z;npV)5O#`0BH>Eh*nK|OnDY;nJj>+{dmj&TJD1#9%ibYq60K-6oW4p)%q5vbqB#I8 zjL5(+xY*(#vPe=i1O*?O!rgiTJ7YC5xu*%ta3aD@UBP2^jyvAxayRz(!-~~vPzo|P zQFR1ZAJgZCvd*#tvPicjU*FpWJwxeVE(VPYDA!^^-*7u$exBG<9O5#i&ZMM_hBeSs zKe(_XeehX2Nj7kdw$cuwPy2VkX&Lj9G$3eJ8UeW@-+$h(gKrj@tu;Ptm-uSu)?<}T8cP*Kd?T1i z6w$f|Laeb_g9Zc;ZPR=^LExLl8^-S+h7S-0HvlIEW<&-ZZFqiG#g;@>VC zorSg}^*`x_)VxIbiDqk^H~gmk{#d$P%H)4J`7tI*7d5$I$9%SvG+88|IrdRK0IO63 zS%^%ltS+U!x@s5ei&(E5lSk-QUr1{Uhdb?JJ;=a5G6HK_9gvnPJVQk+mN1=J zOG_-VSsPI$2Sxt?w*ANJftpzrWB@QxU=%)`J0F$%;RvPFszOK+wi<}_eRuv?tqe0n zBoZ>tPL=>%lYYB)#O-yWAXXCS(wQUk2r4~VRjv;E0DF;hg@m)pvQxzoWn0MP9oS!| z^1$s+DUlXt^4(iTf%%u~?Xbad$P#6`GM)MnVSl&F4BuEOWSYVts(7gKjsb+u1x+`d zKc?E%rN3j)tU|;7*|aWpG7VurDxrGZlNy0cmoSjSLqtF`yXY<>+n5nbW;ki5C&e7Q7~nZ-2` zt<9xij3%$BZ!&X!`dNfvc38$ZM|zxgpzv67^Y;bU`vtahFbWU}OLsAZQprjRI7g+DEYztatri6PVF8R^vq>J$s_zLGj0o+MHJ z6GHir=5sx_VlRKbI3oxPt{9c0tdEEinmtui)v_b2de+z9VPUs#zBu6cjCgL$JTCa0 z&MNZ!sv1sMac`ZRqgk@i#k5=Yw|i_KY|$+blc5l4L_tMvMeVZV*9 z3b{v%zDMT#1yW(k_|}F`+MG3+y837{1yZ0$digS?;(K-~-@q|zu^p$Ah4BVVa~Z?E z-hXE`PqbVin$0t!tn(iA%>Mu{xRtYPltV2+nxqttNhF9z<^TZQNxj9wk~-S`@p76q zM^r^rVl;p@u-mWm#u;T*ykX0(Hf{jpOtzgk&R=(&`9!PZPw2!53P1x9duq=qPGMQy{P@=$WFYoih@+p5b>y}MKivhXqzsr0H zt-i#tG66igy$^WtR6AupZy*^THJ>5WJt`|dut zOp=lU!3BXG?egCeS}MXepELr-(a2ou3T>o=U_So<%N;QMFmnmKN_;Z>bofS+Nh|YQ zu9CMs%4mz~9$fUliHxfCxU9=tO~21>_~vG;pDE%htNEEn<=^}1jlp~o`TdphZ^i{5 z4e>U6N04x*8e}ybJyB6tD#r|UOKIs$jK<0f$0T>Z{{UEA;hIn7L#iIlg}>fIa_fdy z;n~Z-1$mTgyidnmkk2@y$ z*EaJdnyn|8pja!WHFN7dkW)iUrMI%V>~VDX)5Tv0@ZZK;lAI-$@n;TY{IAM*A-E6m zP}Z;DDcY)*N{bmm(PWh=ljWogVqe9lpIoEj&lBDjc_|ieljgjN;Tn9m_R?jt2d5BK zR>$X}G8@P{s&gJl8Bh1d)4U#_|v0Wyww{@yFr|!H+ljqs6q9*&b02al%=)R%3(q zgbpH>^(i8-46#*4#aC;__S+lY;*LIpfq37PIo~b$t>IsRJRFp#T9u@pC9TZfM|Fmp z21`d21zHByY`_M%7|}P14-qtck@&}Dyz`*qT%$7J`Z}H*6_u1VQO^y2Q!ZT{Em&5J zk+L+~9l?v~h0Pm5vaLW)(iO4riSXIw?=x}_7Cdv}8;JO`fw()B^3~*Z$1l+vK66gf zdAf|M-@6GMZKZuzkwH6*T;B;l3!X$~z8kWi6<#j*%Z~ES3(gL#gDK(2+*Aryk&-#) zbdFgar6|l1MU_`_NwzaD;^ohtPx6n$2N!aakX&cM`Oa_6UOTDcjv{=gF^;2LBttDj z9S6{}G*AGfYzvESF*)!_;&yIzcoyW(C;UJ2+m{@a@e9Ee6!|u3PsGv1BvrK0JgN+F zxmIsA9VA&2`W+n{bT|*Bx>|w$!!i)+u8yD^h6H05!oxJ>rw{n)7gfRNhf6`TljIbFN=pfIIAM?`@x)v<1ZC_E6;v7&NC`Z(};4cmn5QslPml> z$nnh$L@Z@P<}#>9C7DYTV{2*4z_$`|4~D!-a`JBzIYe3CBx?muTb_xYUoMzS7Ko}` zL_?I0K#ahD31eeyEzvW?%DWWKbXHegTIp%H(S15Y$reJzR@J zB(xV*dRD1qXxc^^iqxcvZdBW-#*F!^;pdCKA^!jq-X!4c$CO#eg`Co=f*jY4D617G zmXVPR8hLD!Ivy5!_f;!#m-V&0aL)4-XuZ=dTzyh`gGTr&3qu zUy7!hXf&+Fqw@qK zGF-;8uuxANCTf{7_~56eqKLaRge+vAQ+kOT3k+dT74vVEvV0LZE0xrI!QkqSWG5ZR zC2mI@YMR=3{{U@N&RoJhK>{>v3vKEi_VL!w!P_G^T01r+@a<{|hDLhd4Q{%2M zV_#DA!(&$4BCj(VQW*(etYt&4}))nE(ytauPJn9lxmAl*PO8nHGWzhW_#-YYm;!cW9r9!L1I9xXUWl{`6< z6Ft2IO?W>!*;m*_#dMs6iR4yp<_@to(sGyE<1mhgYf zzESZR;qE)iI3GNtrmiqYF-Rn=N_kg9f(o)NzDC3xUycp&z2X}(_&M?CirU^W^Lgh- znb*_P=IfWmq7_W)nweM01IuegB&tap-{p;C{B=3Y%RX*%cf<96EI8kVIO`{+;QF67 ze5SZm#REy0Jc}DR{H>%e$9ztBYn+=;K(_hQJvNpxNOy@?Fkg|3^QsF z-&MSnFVmp!h`KZq%w&Y^;q#Fd{{Rv`8sncFe-LhPX1PBpcsiN*ZjPfa5M|R=M@-&q zh2KLeLXA`-0yWnpjua3Var{sGH#{Wqr-Ys&@onHcnw(q3`4*B}Z-@x3P@cZBgjX6`C@wXE5ADb~z#aEZ+ zRWUU;xI%7WRf>n%|nvjSR|-yJA5F#Jk$7N_?!5n+0$0-f1I@PGnhV-2Nd_K+&_QL*<`P#x8s@xxe8Ll)n-G02CRY zFF5}IDCM_@rQs&ZxLT`;^MaPrt+!gq$tkSZf5ptTE(A6xcwCxK20P!S}86oo{a#fc8pm*juiZqQG zR`OVDu{S=X+!OR9W1{ba2RwOS%dS1~+n94dnH(X&@#gsyZIwx#W>M2NYbsS{E>(`cl5k7lz&*4Mi zzr>dk@m#!1#I(HBgN1WJG-#tR;rd#c;*yur0AKzz0YibPG+^JZGE161BK&God{DeU zau1cf(4Jom{CSpTd|OQk%OI6gCyEwo@Rb^M^@cO3u^`ngk4$1E7lsZ;@xQ}gll~B6 z@zLR@DB?;^DLijen$%ZDVkuCQOZX#A=Z6lTiqKq}5{zxQ17X~ukCGg{de0f~Wd|td| z@i&TZ6I^A%>BNbf@{59Vy8NSr;7HI25G-)iORNn}WtIkSQ9A)^V^knHN|j+8(lRRQ zBXPJQ-(Yc^-Z=ax@MneW=Yb;OUlaVW@fkjM4Q)kayf4T^UrG(ct*8RK zbl8*s0N~rc16GWMkN05!Jx=NmKt6aSOA=WcQowCx>+Re7wkf*9u$EhDsDBbr#sb{# zf*=Zh`;ncv-<*OA9>K7LT{g3x-e9rA)iu#m`?YB>SQj)8f*fW`3EV_?C z2_1c~s@_)`*tB-I)HeCw1lP3WsV0)JR7}UsLEFw0KpV$Zb{ti zqUDA@TeO@~Jv0t4HB0C_Kf>QMqZj11VepRdpxo8xEIiZV44_nU^MYz3%r(pjj=wr9 zdTMZch=B9kt+d7u=EqskX0lMiiB&AC5-pUKEOh&lF^wJ?`3=InfaO;Sa({wU3OXn} z$*UL@lQOI+u4;)#XLrsue|Sp2ZZ*DrEDBEEs|69@vZ5 z=7yRjSs|&NSe?-WTjW6A_;8mq%T}6M1dS|?cG9H$?TGaTVJ=~qOO~ZNBC+(dJ%`-( z-xWMSc?8laY8T>9;IfOKG)>N~QDs&1JoL(8RjH+o0xuHMMm;fV=qi*FBY)ysq5d0l z@53C>%=mvgtIP9TxiUva{rwctXqpF7RnfHppp7G91&>fS$8x!bSQeUisun28ItbOP zSIg&(LwM-;Yw*{IX=-_=${~|*mpULo^-D9DsJN6S;VMWTiLGEJvDIrm{{S%Rz25hP zcyyynsdw&=UUmH!!*;8(EY`Hm79_8*tw3bC%`Rk+*G* z4W4FniZLyTx!HST5_4WG<|ik3-#OrZXzob#)zpa=Tz`<~wDi?bP9vF=213>Wh$PsKyN~COROoo7n^e&F92`9t0@iSeA$e?qh*Qbb zh7hYs9e~tt{{T?#clN?_sB$DIAuNNcfC=8$A3NYkD&Bb^bW}zg3o&n{{@7K###v-` z^{ZWthg*&IA52_$0c#%}93-Tk7|RBU!`k6*x9foevq-WZHInvw+os!nF;Nn-s)j-Z z_HO(4`C%m@CejPB-s^jd+u!|85wO}I2};V6231C6LAKpa_rT3BnA#Nuw?3xY{{ZSR zy9HDzSnaztx_`a{l2B<%nS9k2TiA=9$9w}{R;0&iAR>{Z^B+?kO?5j1{fr3(Op*Te zWRfh`8r4WXXv(2MEmfMTnucaf%dsB$!t-3^7# z{{Uie1T&bqC~nj`$L2!!&IwpNB8){ZA>L}Vznm}2F0ba;Sn1Q#uJ`vh-xRVWf!u>FhRoI;X8nF$Kb`_9 z0Mcqqst6@|+Slp_w%5iP97xI;0zN#(x~U{O4Rd?gYPhw& ze*55QqK26W((f~G>1%=j+v;)bp-nWii4Y=@YY=zZ_+fj2$xCcNrDmDtQm8{J8?jA; ze8~A?xGU;o9zr`6@sKkNLk>$HnV{iKq}BZe~RVX2CXl6}u>oHsOxt0Zr&7!Im!gKWMzi9^^fk?9-z zeRsjCP}3k)D`r*Hr=wr~I^i#jjHxX>64AKH5~9(=la5|T|`%1!;AGDLfmiHrYx5* z{6JGpPfbQSs4UE<5~ z$nSf}A^gqMh}0H6hkSg`AMJEHI7`dJR`-Q=eqBSuS}yu1KMnA&G5kjJ5`%}hZjOBS zi0h{@!xp2V1;IX}vPPiXu_07-BW!i+;CI1)E4(Ul=+Gr*O~m}j&C({$^SI8=_tYt= zNjjFD4&wW}4QAT_e}sPpyrS^E!Bgr-})N0Ge;pjNrI{jngJQaxhFR`ilWmsScvx3Sx(#8OJn!z4xAC{e+Lq!ZyMt>`7 zCgTMoKq+D6LFE*bK4a3y9>0;jzh3xidDclDd1EZZZrW@~_qf8f4@n%3lh;$Do&86B z``{|-8g_&%HS$KlfOIz3`gX>r#LC%tW2$Yf%yQs`=6Ml%->3&~d@>C0F9pPTglGvK zpO^b@hl589L(4NsIW43HKrByuGG~=kaWFB%6_i-|2HW-f;9l`~QX>Il4~ZWPypZud z!*7yv6NM;qis*s-25ABEYx36o*M?!Z7aO6vk=q>h^PAy|;wOeY znlx3-DdQlEGzZfuQGMe++heH%H4?FzDWW8y-Bb^##BRD+8r5=yMnkxL0` zMLIN|Q1cUbpKXo3$MwbA;(vtCIWki}{*UJm2ymYLX--o=Ig0N8u&X(#w{ z_`;@nrHZ40>seH)GUq@Y>_3Tpu0Gi4dS3T43@64|_V9gg+0PZPYK1@E6DNF z)tLZRa5Ueb{t@@T>yM`5%&12RlD;TJsjUbE++2W3?YKL3z8KHL+r}!HQ8;rZQmd$y z&ms!e>to*CZSuf%pAXL#i5|A$+=fuCq+2?Ol5BcyewbUk%HfBUqv8-A!|OUQr(w)I zf=Oe6Yhg77tfx(aU+480CT=p}_-2u6vr!R^Y|6vbLE7W|+uM9Z)8X^t&CAA|C6zOh zPWi+jn;as3AKojx?Gtd8SQ&3%b9nb2;@w6h_mjhj%!A^Z-oxs^`h`qaiSkCL{9IX` zG?boTjhI-vk{E(huker$Onpzr+$xcIubH-sfT&R2n2YW^3|qN;0{EkVF{t3`0N>{Q zsTl(M{$aNEI9Dq08{%5DF&rh8Ngm@t&LdVkeKx|Q?=yx2?8-hNNB19Eap9kWoi`tF ztxP3`ZyhtQQ1LOpTZ<0+3?WO$Tp-$HT-9{Obw~_taHNi#{{Uk6jc0xVd_`rE(s@~4 zQdUJ~dTDb+N2Va#cKoaj$=cSjxENti0zM?=XNo+VhncP~8s||HxgD@>?=OafW>)-F zkM16~Z3xPqNz6VDgtNn5ts`G$Q+C|{0LIu-pO1J{r9=7CThpzyX*M^u-)+yi#87-b zd{jM}P8-OhxVr1jCHTb8Gv4Ti>v@9O?O`!YyFwp>&jCGOwU^usfa4LGO!ro&vl` zyheEP%!IzyRm~LHceyME+kv&a;0@!mR(RRvRXUFkKF+6YaiDF&CLD{Sf!|ns-ep^wT3iO zO~%64vD(MwhDP{&_?9~4Y`=x2u>Ks>4PXB4zh7~ITjBBIT&!{~N5b=?{{Rrq6Xn+9 zt`0u*ICHs5+xMn_aJ8UUhEwHFHMmMDbY}gjEY~52mV(>f#Omv~-|LSDGq`TjKo>EI z%Xx*2X=DH$wr-~V4kNW*0K7%g!xZ&dKMx`~7SWk2n{*`EcCo_r-T=A#R~+pWJTCPh zp^O~SS4g?kUg>{fwihRP`UCZ)ZF|$%*gaSnjHlXeXK>JnmlH(W`C+t=GRJ=XeqHdb zS2p-si&~_0k~*+LN0($fUfbcQd^_2ybcX}K=01S=zp#I=%x-h3$d7r|qGQlt6VlJxJ3Z)Pq^Agv-*09^> zf+OaK3;+ymRv0fpi@p1>)%3$GUk*8~YLE?Sn_dXT+h2s!8B^ zSw^9!G&`@j0WNS6_p!r)%&qvT9p7sRqZv+d^Gk)jW?APgsD`?r1d*^C{E6S+13xvm zUF1S0sEpf49$J7;we?&702l%fhWCi-h=-co4N3{Q66Q<@`*~*laI$A|hZrm}IEJBDR=HVKO_+Si>3#2q zTFzx~og}bAm2_35)qr><3?gM>wjgyZJwxT!e)NFe%iIS*^}^2Xx$!QQV8X}8ENOMAW79&waQ^IwJ48YwC!(!r5U zfma}P1U1h80Bjdc%x)4>Oww1!7n?7X$Xe}AI_hD4mwvw^?S!ECWO$9L3}NC`+Js91L@RrDeil3`>Z*=?eM?n3LV|%uw*cxXXB0; zg089xe92m9nTMI?FP9?T#HqRT_rKoQR!(AYtu&0oF@mll7x${@RZWjjP5%Jj4l(>K zJVpjYmy3C09fiyOE~nA@MY+S6_*Qs_38qdu;bZ>*C{g|% zYtJauULHE(>b#dV&Ec!3fhj)>2$ob5%4Bv>QAykaq@R_q*9lVdM}+BGou;goIb|S6 z<`n^r?0fCF-xH|56h0v;fn&#gd8gug$eaKHPD%Lrlz zN^Mzo_OSB({{T#5`{3b&*)jw1O#c85HN5r}2Zx*78&ND2ubUKm(y5oG~W7j z@8A14bf@?}bHbryan0UayeKR!Nmvc-djVno*ii3>hBTkv3ilt$F`eA&fW4~C)pJ{g z5W^(;B88QT6_ho=w_UoM_VzfA)_8*9Y^@ohN{X1u=mHb7y@yi$2Iqg4GQ%(UGxGwe z^=G{M;aYfLOa z^_}-{+PIy#`--_2c6!$vAbeJz_^ZS=Z<~qX$*Es0q&H-dr7a>};>=dU_O=@NdC9L3 zo+I<9DEV)|TwTV1zLuzlA}Fbay2(){n3N6s-q`7Dmp=|43tYLCD{?McWV}t9#>302 z;yE6^Kz;N`e6Ylx$=eydlH}R0K@ApHm(XN+c2^54BrqqJ97<0`jclqq>;^s?jrY#^ z+fcCmroQj$zN?3KV#ZVFcfn~(!+*icFQuN7i2O%!JUmHK86_M)lFZ3X{{Y)jRkO+e z0NW5z+g3N5!F;>mjswXu?ik>H7@^@jiiH*^X(&)d6lyz#Tio8{o}`m}Jmu?|kt|iI zNVP!Rd29{E{{WWQlhVLjLza6L1+@A}`ClAYit+7UwoUqn+4AT<#nE&;A5Wxa*jryT z^F*-`8HQOjFt8vUK-*)|_qaGF9Ei#tO+{TAkP8)K>LcV%*h-El;w}~lqj9)ndyTt& zFl`_0W^@%bk<>-K#D1H7Z;EilU-ineZAh}iEfFs?r!hC#q}-jXF(O*{XNA*FhHuP7 zV@jUK=ZN%luM|uYrlChx(7=E{*9Ebu1>#3(0UE4*C;tGnTNh$;qc}*FmY*SqD+>&- zLad~PZ3<53-pA$q@T76mq6LnExmSA)R<{2DTn9^4m_Z7e-w|k4>>Nlp5 Z5=X0+1|S^-pHK3}(T_4^P;&@h|Jem-?34fi literal 0 HcmV?d00001 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index f174717b4..7249942d1 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -772,7 +772,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } else { tDecodedData |= tMask; } - IR_TRACE_PRINTLN('1'); + IR_TRACE_PRINTLN(F("=> 1")); } else { #if defined DECODE_STRICT_CHECKS /* @@ -811,7 +811,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } #endif // do not set the bit - IR_TRACE_PRINTLN('0'); + IR_TRACE_PRINTLN(F("=> 0")); } #if defined DECODE_STRICT_CHECKS // If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it @@ -1225,7 +1225,7 @@ void printActiveIRProtocols(Print *aSerial) { aSerial->print(F("Lego Power Functions, ")); #endif #if defined(DECODE_BOSEWAVE) - aSerial->print(F("Bosewave , ")); + aSerial->print(F("Bosewave, ")); #endif #if defined(DECODE_MAGIQUEST) aSerial->print(F("MagiQuest, ")); diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index 6ca549931..c8ec9b7a1 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -30,10 +30,10 @@ // // Support for Bose Wave Radio CD initially provided by https://github.com/uvotguy. // -// As seen on my trusty oscilloscope, there is no repeat code. Instead, when I +// As seen on my oscilloscope, there is no repeat code. Instead, when I // press and hold a button on my remote, it sends a command, makes a 51.2ms space, -// and resends the command, etc, etc. -// LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit. +// and resends the command again, and so on. +// 38 kHz, LSB first, 1 start bit + 8 bit data + 8 bit inverted data + 1 stop bit. #define BOSEWAVE_BITS 16 // Command and inverted command #define BOSEWAVE_HEADER_MARK 1014 // 1014 are 39 clock periods (I counted 3 times!) diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index a7aba5f56..9f99ebf32 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -45,6 +45,7 @@ // from LEGO Power Functions RC Manual 26.02.2010 Version 1.20 // https://github.com/jurriaan/Arduino-PowerFunctions/raw/master/LEGO_Power_Functions_RC_v120.pdf // https://oberguru.net/elektronik/ir/codes/lego_power_functions_train.lircd.conf +// For original LEGO receiver see: https://www.philohome.com/pfrec/pfrec.htm and https://www.youtube.com/watch?v=KCM4Ug1bPrM // // To ensure correct detection of IR messages six 38 kHz cycles are transmitted as mark. // Low bit consists of 6 cycles of IR and 10 �cycles� of pause, diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index a7243dead..335f33c68 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1397,6 +1397,9 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { } # endif // defined(SEND_PWM_BY_TIMER) +/********************************************************** + * ESP8266 boards + **********************************************************/ #elif defined(ESP8266) # if defined(SEND_PWM_BY_TIMER) #error "No support for hardware PWM generation for ESP8266" @@ -1435,8 +1438,8 @@ void timerConfigForReceive() { // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL) -#define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) +#define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif void timerEnableReceiveInterrupt() { @@ -1490,14 +1493,14 @@ uint8_t sLastSendPin = 0; // To detach before attach, if already attached # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution + ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution # else ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API # endif } void disableSendPWMByTimer() { # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0); + ledcWrite(SEND_LEDC_CHANNEL, 0); # else ledcWrite(IrSender.sendPin, 0); // New API # endif @@ -1509,14 +1512,14 @@ void disableSendPWMByTimer() { */ void timerConfigForSend(uint16_t aFrequencyKHz) { # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution + ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution # if defined(IR_SEND_PIN) - ledcAttachPin(IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // attach pin to channel + ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttachPin(IrSender.sendPin, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL); // attach pin to channel + ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel sLastSendPin = IrSender.sendPin; # endif # else // New API here From 8e75076a67ac0cbdf7b21ed347761379273ec125 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 25 Apr 2024 21:16:40 +0200 Subject: [PATCH 040/133] Documentation + improved Samsung + improved IRremoteExtensionTest example --- README.md | 11 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 11 +- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 6 - examples/ControlRelay/ControlRelay.ino | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 6 - .../IRDispatcherDemo/PinDefinitionsAndMore.h | 6 - .../IRremoteExtensionClass.cpp | 26 ++- .../IRremoteExtensionClass.h | 5 +- .../IRremoteExtensionTest.ino | 15 +- .../PinDefinitionsAndMore.h | 6 - examples/MicroGirs/MicroGirs.ino | 11 +- examples/MicroGirs/PinDefinitionsAndMore.h | 6 - .../ReceiveAndSend/PinDefinitionsAndMore.h | 6 - examples/ReceiveAndSend/ReceiveAndSend.ino | 12 +- .../PinDefinitionsAndMore.h | 6 - .../ReceiveAndSendDistanceWidth.ino | 9 +- .../PinDefinitionsAndMore.h | 6 - examples/ReceiveDemo/PinDefinitionsAndMore.h | 6 - examples/ReceiveDemo/ReceiveDemo.ino | 13 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 6 - examples/ReceiveDump/ReceiveDump.ino | 11 +- .../PinDefinitionsAndMore.h | 6 - .../SendAndReceive/PinDefinitionsAndMore.h | 6 - .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 6 - examples/SendDemo/PinDefinitionsAndMore.h | 6 - examples/SendDemo/SendDemo.ino | 5 +- .../PinDefinitionsAndMore.h | 6 - .../SendProntoDemo/PinDefinitionsAndMore.h | 6 - examples/SendRawDemo/PinDefinitionsAndMore.h | 6 - .../SimpleReceiver/PinDefinitionsAndMore.h | 6 - .../PinDefinitionsAndMore.h | 6 - examples/SimpleSender/PinDefinitionsAndMore.h | 6 - examples/TinyReceiver/PinDefinitionsAndMore.h | 6 - examples/TinySender/PinDefinitionsAndMore.h | 6 - examples/UnitTest/PinDefinitionsAndMore.h | 6 - examples/UnitTest/UnitTest.ino | 54 ++++-- examples/UnitTest/UnitTest.log | 162 +++++++++--------- src/IRProtocol.h | 2 +- src/IRremoteInt.h | 1 + src/ir_BangOlufsen.hpp | 39 +++-- src/ir_Pronto.hpp | 3 + src/ir_Samsung.hpp | 41 ++++- 42 files changed, 258 insertions(+), 313 deletions(-) diff --git a/README.md b/README.md index db3f67a1c..779107c48 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) - [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) - * [Receiving does not run if analogWrite() or tone() is used.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-does-not-run-if-analogwrite-or-tone-is-used) + * [Receiving stops after analogWrite() or tone() or after running a motor.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor) * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc) * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library) * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver) @@ -508,10 +508,11 @@ void loop() {} The FAST protocol can be received by IRremote and TinyIRReceiver. # FAQ and hints -## Receiving does not run if analogWrite() or tone() is used. +## Receiving stops after analogWrite() or tone() or after running a motor. The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). On some boards where a software timer is available, the software timer is used.
-Be aware that the hardware timer used for receiving should not be used for analogWrite().
-On the Uno and other AVR boards the receiver timer ist the same as the tone timer, so 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. +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()`. ## 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).
@@ -969,5 +970,5 @@ From the version 2.8.0, the license is the MIT license. # Copyright Initially coded 2009 Ken Shirriff http://www.righto.com
-Copyright (c) 2016-2017 Rafi Khan
+Copyright (c) 2016-2017 Rafi Khan https://rafikhan.io
Copyright (c) 2020-2024 [Armin Joachimsmeyer](https://github.com/ArminJo) diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index ecdd71148..9a9e9cc34 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -36,12 +36,13 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ControlRelay/ControlRelay.ino b/examples/ControlRelay/ControlRelay.ino index 1460872f4..ebf77089f 100644 --- a/examples/ControlRelay/ControlRelay.ino +++ b/examples/ControlRelay/ControlRelay.ino @@ -35,7 +35,7 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -#if FLASHEND <= 0x1FFF || (RAMEND <= 0x4FF || RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167 +#if FLASHEND <= 0x1FFF || (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167 #define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. #define EXCLUDE_EXOTIC_PROTOCOLS #endif diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 3ec6be4cc..821c387b3 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2021 Armin Joachimsmeyer + * Copyright (c) 2021-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,14 +31,32 @@ */ #include +/* + * !!! The value of RAW_BUFFER_LENGTH (and some other macros) must be the same in all compile units !!! + * Otherwise you may get warnings like "type 'struct IRData' itself violates the C++ One Definition Rule" + */ +#if !defined(RAW_BUFFER_LENGTH) +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 +# else +#define RAW_BUFFER_LENGTH 750 +# endif +#endif + #include "IRremoteExtensionClass.h" IRExtensionClass::IRExtensionClass(IRrecv *aIrReceiver) { MyIrReceiver = aIrReceiver; } -void IRExtensionClass::decode() { - Serial.println(F("Call decode()")); - MyIrReceiver->decode(); +bool IRExtensionClass::decode() { + return MyIrReceiver->decode(); +} + +bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) { + return MyIrReceiver->printIRResultShort(aSerial,aPrintRepeatGap,aCheckForRecordGapsMicros); } void IRExtensionClass::resume() { diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h index 700ad0ee3..2fa648a7c 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2021 Armin Joachimsmeyer + * Copyright (c) 2021-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,7 +39,8 @@ class IRExtensionClass public: IRrecv * MyIrReceiver; IRExtensionClass(IRrecv * aIrReceiver); - void decode(); + bool decode(); + bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap = true, bool aCheckForRecordGapsMicros = true); void resume(); }; diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index 65b42c03c..7f37f1f14 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -33,12 +33,13 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -70,8 +71,8 @@ void setup() { } void loop() { - if (IrReceiver.decode()) { - IrReceiver.printIRResultShort(&Serial); + if (IRExtension.decode()) { + IRExtension.printIRResultShort(&Serial); IrReceiver.printIRSendUsage(&Serial); IRExtension.resume(); // Use the extended function provided by IRExtension class } diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index 52e6c3a8c..ad9cb182a 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -67,12 +67,13 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 500 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 10f7fe86d..45b139eb4 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -22,7 +22,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2009-2023 Ken Shirriff, Armin Joachimsmeyer + * Copyright (c) 2009-2024 Ken Shirriff, Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -69,11 +69,15 @@ //#define DECODE_WHYNTER //#define DECODE_FAST // + #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 120 -# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 120 // 180 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; +# elif (defined(RAMEND) && RAMEND <= 0xAFF) || (defined(RAMSIZE) && RAMSIZE < 0xAFF) +#define RAW_BUFFER_LENGTH 500 // 750 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; # else #define RAW_BUFFER_LENGTH 750 # endif diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 1f9813583..93c6e8edb 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -56,10 +56,11 @@ #define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols // #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 120 -# elif RAMEND <= 0xAFF || RAMSIZE < 0xAFF // 0xAFF for LEONARDO -#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else #define RAW_BUFFER_LENGTH 750 # endif diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 002c21812..f9941e01d 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -73,14 +73,13 @@ // #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 130 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active -#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index b716ba104..e36562548 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -36,12 +36,13 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 600 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 600 # else -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index bbcc94960..28e108288 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -60,6 +60,7 @@ void setup() { #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 # if defined(IR_SEND_PIN_STRING) Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING)); # else @@ -132,7 +133,7 @@ void loop() { delay(DELAY_AFTER_SEND); if (sRepeats == 0) { -#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. +#if FLASHEND >= 0x3FFF && ((defined(RAMEND) && RAMEND > 0x6FF) || (defined(RAMSIZE) && RAMSIZE > 0x6FF)) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. /* * Send constant values only once in this demo */ @@ -334,7 +335,7 @@ void loop() { IrSender.sendRC6(sAddress, sCommand, sRepeats, true); delay(DELAY_AFTER_SEND); -#if FLASHEND >= 0x3FFF && (RAMEND >= 0x4FF || RAMSIZE >= 0x4FF) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. +#if FLASHEND >= 0x3FFF && ((defined(RAMEND) && RAMEND > 0x4FF) || (defined(RAMSIZE) && RAMSIZE > 0x4FF)) // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. /* * Next example how to use the IrSender.write function */ diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index d53c88aae..048395099 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -331,12 +331,6 @@ void noTone(uint8_t aPinNumber){ #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0xFFFF // Dummy value for platforms where RAMEND is not defined -#endif -#if !defined (RAMSIZE) -#define RAMSIZE 0xFFFF // Dummy value for platforms where RAMSIZE is not defined -#endif /* * Helper macro for getting a macro definition as string diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index bc75f6fb3..c450152a8 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -36,12 +36,13 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -# if RAMEND <= 0x4FF || RAMSIZE < 0x4FF -//#define RAW_BUFFER_LENGTH 180 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# elif RAMEND <= 0x8FF || RAMSIZE < 0x8FF -#define RAW_BUFFER_LENGTH 150 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +#define RAW_BUFFER_LENGTH 180 +# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define RAW_BUFFER_LENGTH 200 // 600 is too much here, because then variables are overwritten. 500 is OK without Pronto and 200 is OK with Pronto # else -#define RAW_BUFFER_LENGTH 200 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -55,6 +56,8 @@ // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. //#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity. +//#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols. + //#define TRACE // For internal usage //#define DEBUG // Activate this for lots of lovely debug output from the decoders. @@ -80,9 +83,9 @@ #define DECODE_LG #define DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here. -//#define ENABLE_BEO_WITHOUT_FRAME_GAP // For successful unit testing we must see the warning at ir_BangOlufsen.hpp:88:2 +//#define ENABLE_BEO_WITHOUT_FRAME_GAP // !!!For successful unit testing we must see the warning at ir_BangOlufsen.hpp:100:2!!! #if defined(DECODE_BEO) -#define RECORD_GAP_MICROS 16000 // always get the complete frame in the receive buffer +#define RECORD_GAP_MICROS 16000 // Force to get the complete frame including the 3. space of 15 ms in the receive buffer #define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz here (instead of 455 kHz). #endif @@ -137,6 +140,9 @@ void setup() { Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); #endif + Serial.println(F("Use ReceiveCompleteCallback")); + Serial.println(F("Receive buffer length is " STR(RAW_BUFFER_LENGTH))); + #if defined(IR_SEND_PIN) IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin # if defined(IR_SEND_PIN_STRING) @@ -279,7 +285,7 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize) /* * Test callback function - * Has the same functionality as available() + * Has the same functionality as a check with available() */ void ReceiveCompleteCallbackHandler() { sDataJustReceived = true; @@ -287,7 +293,14 @@ void ReceiveCompleteCallbackHandler() { void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { // wait until signal has received + uint16_t tTimeoutCounter = 1000; // gives 10 seconds timeout while (!sDataJustReceived) { + delay(10); + if (tTimeoutCounter == 0) { + Serial.println(F("Receive timeout happened")); + break; + } + tTimeoutCounter--; } sDataJustReceived = false; @@ -397,12 +410,13 @@ void loop() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. if (sAddress == 0xFFF1) { -# if FLASHEND >= 0x7FFF // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc. +# if FLASHEND >= 0x7FFF && ((defined(RAMEND) && RAMEND <= 0x6FF) || (defined(RAMSIZE) && RAMSIZE < 0x6FF)) // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc. /* * Send constant values only once in this demo */ Serial.println(F("Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats")); Serial.flush(); + // This is copied to stack/ram internally IrSender.sendPronto(F("0000 006D 0022 0000 015E 00AB " /* Pronto header + start bit */ "0017 0015 0017 0015 0017 0017 0015 0017 0017 0015 0017 0015 0017 0015 0017 003F " /* Lower address byte */ "0017 003F 0017 003E 0017 003F 0015 003F 0017 003E 0017 003F 0017 003E 0017 0015 " /* Upper address byte (inverted at 8 bit mode) */ @@ -662,15 +676,15 @@ void loop() { #endif #if defined(DECODE_SAMSUNG) - Serial.println(F("Send Samsung 8 bit command")); + Serial.println(F("Send Samsung 8 bit command and 8 bit address")); Serial.flush(); - IrSender.sendSamsung(sAddress, sCommand, 0); - checkReceive(sAddress, sCommand); + IrSender.sendSamsung(sAddress & 0xFF, sCommand, 0); + checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Samsung 16 bit command")); + Serial.println(F("Send Samsung 16 bit command and address")); Serial.flush(); - IrSender.sendSamsung(sAddress, s16BitCommand, 0); + IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, 0); checkReceive(sAddress, s16BitCommand); delay(DELAY_AFTER_SEND); @@ -733,7 +747,7 @@ void loop() { Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); IrSender.write(&IRSendData, 0); - checkReceive(IRSendData.address, IRSendData.command); + checkReceive(IRSendData.address & 0xFF, IRSendData.command); delay(DELAY_AFTER_SEND); #endif @@ -761,7 +775,8 @@ void loop() { IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0); # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) delay((RECORD_GAP_MICROS / 1000) + 1); - Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled. PrintRaw and try to decode")); + Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); + Serial.println(F("- Now print raw data and try to decode it, which must fail!")); IrReceiver.printIRResultRawFormatted(&Serial, true); uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawlen; IrReceiver.decodedIRData.rawlen = 6; @@ -769,8 +784,11 @@ void loop() { IrReceiver.decode(); IrReceiver.printIRResultShort(&Serial); - // Remove trailing 6 entries for next decode try - Serial.println(F("- Remove trailing 6 entries for next decode try")); + // Remove trailing 6 entries for second decode try + Serial.println(); + Serial.println( + F( + "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode")); IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6]; diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index f19594994..d89d0a7b9 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -1,6 +1,8 @@ START ../src/UnitTest.cpp from Feb 22 2023 Using library version 4.1.0 Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2 +Use ReceiveCompleteCallback +Receive buffer length is 200 Send IR signals at pin 3 If you connect debug pin 5 to ground, raw data is always printed Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us @@ -436,60 +438,60 @@ rawData[42]: +1200,- 550 +1200,- 600 +1250,- 600 +1200 Sum: 35350 -Send Samsung 8 bit command -Protocol=Samsung Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first -Send with: IrSender.sendSamsung(0xFFF1, 0x76, ); +Send Samsung 8 bit command and 8 bit address +Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first +Send with: IrSender.sendSamsung(0xF1, 0x76, ); rawData[68]: - -1039650 - +4400,-4450 - + 550,-1700 + 550,- 550 + 600,- 550 + 550,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 550,-1650 - + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,- 550 + 550,-1650 + 600,-1650 + 600,- 550 - + 550,-1650 + 600,-1650 + 550,-1700 + 550,- 550 - + 600,-1650 + 550,- 550 + 600,- 550 + 600,-1600 - + 600,- 550 + 600,- 550 + 550,- 550 + 600,-1650 - + 600 -Sum: 68750 + -1045200 + +4500,-4400 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 650,- 450 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,- 500 + 650,- 450 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650 +Sum: 65600 -Send Samsung 16 bit command +Send Samsung 16 bit command and address Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); rawData[68]: - -1056350 - +4400,-4400 - + 600,-1650 + 550,- 550 + 600,- 550 + 550,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1600 - + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,- 500 + 550,-1700 + 600,-1650 + 550,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550 - + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650 - + 550,-1650 + 600,- 550 + 600,- 550 + 550,-1650 - + 600 -Sum: 68650 + -1060350 + +4500,-4400 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,-1600 + 600,-1650 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550 + + 600,-1600 + 650,-1600 + 600,-1650 + 650,- 450 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,-1600 + 600,- 550 + 600,- 500 + 650,-1600 + + 650 +Sum: 68950 Send Samsung48 16 bit command Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); rawData[100]: - -1056750 - +4450,-4450 - + 600,-1650 + 600,- 500 + 600,- 550 + 550,- 550 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650 - + 550,-1650 + 550,-1700 + 550,-1700 + 550,-1650 - + 600,- 550 + 550,-1700 + 550,-1650 + 600,- 550 - + 550,-1650 + 600,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650 - + 550,- 550 + 600,- 550 + 550,- 550 + 550,-1700 - + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 - + 550,-1650 + 600,- 550 + 550,- 550 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550 - + 550,- 550 + 600,-1650 + 550,-1650 + 600,- 550 - + 550 -Sum: 95650 + -1060200 + +4550,-4350 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 + + 650 +Sum: 95900 Send RC5 Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first @@ -543,18 +545,18 @@ Send Samsung Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); rawData[68]: - -1036350 - +4450,-4400 - + 550,-1700 + 600,- 550 + 550,- 550 + 600,- 550 - + 550,-1650 + 600,-1650 + 600,-1650 + 550,-1650 - + 550,-1700 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650 - + 550,- 550 + 600,-1650 + 550,-1700 + 550,- 550 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550 - + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650 - + 550,-1650 + 600,- 550 + 600,- 500 + 600,-1700 - + 550 -Sum: 68750 + -1039800 + +4550,-4400 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 + + 650 +Sum: 69000 Send LG Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first @@ -594,38 +596,40 @@ rawData[112]: Sum: 63750 Send Bang&Olufsen -- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled. PrintRaw and try to decode +- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled +- Now print raw data and try to decode it, which must fail! rawData[112]: - -1049800 - + 300,-2900 + 200,-2850 + 250,-15200 + 300,-2850 - + 250,-9000 + 300,-5900 + 300,-5950 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-5950 + 250,-9000 - + 300,-2850 + 250,-9050 + 250,-5900 + 300,-5950 - + 250,-2850 + 250,-9000 + 300,-5950 + 250,-2850 - + 250,-12100 + 300,- 800 + 650,- 500 + 650,- 500 + -1053350 + + 250,-2850 + 250,-2850 + 250,-15250 + 250,-2850 + + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050 + + 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950 + + 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850 + + 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 - + 350,- 800 + 350,- 800 + 650,- 500 + 350,- 800 + + 350,- 800 + 350,- 800 + 650,- 550 + 300,- 800 + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 500 + 350,- 850 - + 350,- 800 + 350,- 750 + 650,- 500 + 650,- 500 - + 300,- 850 + 650,- 500 + 650,- 500 + 650 + + 350,- 800 + 650,- 500 + 650,- 550 + 300,- 850 + + 300,- 850 + 350,- 800 + 600,- 550 + 600,- 550 + + 300,- 850 + 600,- 550 + 600,- 550 + 650 Sum: 176100 -Protocol=UNKNOWN Hash=0x643E0496 22 bits (incl. gap and start) received -- Remove trailing 6 entries for next decode try +Protocol=UNKNOWN Hash=0x4E0DAC41 22 bits (incl. gap and start) received + +- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, ); rawData[44]: - -1078450 - + 150,-2850 - + 200,-2900 + 200,-15300 + 200,-2900 + 200,-9100 - + 250,-5950 + 250,-5950 + 250,-5950 + 200,-2900 - + 200,-6000 + 200,-6000 + 200,-9100 + 200,-2900 - + 200,-9100 + 250,-5950 + 250,-5950 + 250,-2850 - + 200,-9100 + 250,-5950 + 250,-2850 + 200,-12200 - + 200 -Sum: 136500 + -15250 + + 250,-2850 + + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050 + + 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950 + + 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850 + + 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500 + + 650 +Sum: 118700 Send Bosewave with no address and 8 command bits Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 95f59b039..5f9ed1bb2 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2023 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 452231961..07b9380ff 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -539,6 +539,7 @@ class IRsend { void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true); void sendSamsungLGRepeat(); void sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); + void sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); void sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNumberOfRepeats); void sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 2649d74c6..d54f6d500 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -63,13 +63,15 @@ // It might be that this only happens over IR and not on the datalink protocol // You can choose to support this or not: -// Alt 1: Mode with gaps between frames -// Set RECORD_GAP_MICROS to at least 16000 to accommodate the unusually long 3. start space -// Can only receive single messages and back to back repeats will result in overflow - -// Alt 2: Break at start mode -// Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to 13000 to treat the 3. start space as a gap between messages -// The start of a transmission will result in a dummy decode with 0 bits data followed by the actual messages +// Mode 1: Mode with gaps between frames +// Set RECORD_GAP_MICROS to at least 16000 to accept the unusually long 3. start space +// Can only receive single messages. Back to back repeats will result in overflow + +// Mode 2: Break at start mode +// Define ENABLE_BEO_WITHOUT_FRAME_GAP and set RECORD_GAP_MICROS to less than 15000 +// to treat the 3. start space of 15.5 ms as a gap between messages, which makes decoding easier :-). +// The receiving of a transmission will then result in a dummy decode of the first 2 start bits with 0 bits data +// followed by a 15.5 ms gap and a data frame with one start bit (originally sent as 4. start bit). // If the receiver is not resumed within a ms or so, partial messages will be decoded // Debug printing in the wrong place is very likely to break reception // Make sure to check the number of bits to filter dummy and incomplete messages @@ -82,6 +84,7 @@ // Header data with more than 16 bits is stored in decodedIRData.extra // B&O is a pulse distance protocol, but it has 3 bit values 0, 1 and (equal/repeat) as well as a special start and trailing bit. +// // MSB first, 4 start bits + 8 to 16? bit address + 8 bit command + 1 special trailing bit + 1 stop bit. // Address can be longer than 8 bit. @@ -93,12 +96,12 @@ //#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory. #if defined(DECODE_BEO) # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) -# if RECORD_GAP_MICROS > 13000 -#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to 1300 by "#define RECORD_GAP_MICROS 13000" +# if RECORD_GAP_MICROS > 15000 +#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 13000" # endif # else # if RECORD_GAP_MICROS < 16000 -#error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 1600 by "#define RECORD_GAP_MICROS 16000" +#error If not defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to a value >= 16000 by "#define RECORD_GAP_MICROS 16000" # endif # endif #endif @@ -313,7 +316,7 @@ bool IRrecv::decodeBangOlufsen() { #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) /* - * Check if we have the AGC part of the first frame in a row + * Check if we have the AGC part of the first frame, i.e. start bit 1 and 2. */ if (decodedIRData.rawlen == 6) { if ((matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_IR_MARK) @@ -321,7 +324,7 @@ bool IRrecv::decodeBangOlufsen() { && (matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK) || matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_DATALINK_MARK))) { BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN)); - BEO_TRACE_PRINTLN(F("B&O: AGC only part detected")); + BEO_TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected")); } else { return false; // no B&O protocol } @@ -336,11 +339,11 @@ bool IRrecv::decodeBangOlufsen() { } if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_IR_MARK)) { -#if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) +# if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) protocolMarkLength = BEO_IR_MARK; } else if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_DATALINK_MARK)) { protocolMarkLength = BEO_DATALINK_MARK; -#endif +# endif } else { BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_TRACE_PRINTLN(F(": mark length is wrong")); @@ -351,7 +354,7 @@ bool IRrecv::decodeBangOlufsen() { for (uint8_t tRawBufferMarkIndex = 3; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) { #else for (uint8_t tRawBufferMarkIndex = 1; tRawBufferMarkIndex < decodedIRData.rawlen; tRawBufferMarkIndex += 2) { -#endif +#endif // defined(ENABLE_BEO_WITHOUT_FRAME_GAP) uint16_t markLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex]; uint16_t spaceLength = decodedIRData.rawDataPtr->rawbuf[tRawBufferMarkIndex + 1]; @@ -380,11 +383,11 @@ bool IRrecv::decodeBangOlufsen() { } else { if (tPulseNumber == 3) { if (matchMark(markLength, BEO_IR_MARK)) { -#if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) +# if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) protocolMarkLength = BEO_IR_MARK; } else if (matchMark(markLength, BEO_DATALINK_MARK)) { protocolMarkLength = BEO_DATALINK_MARK; -#endif +# endif } else { BEO_DEBUG_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_DEBUG_PRINTLN(F(": 4. (start) mark length is wrong")); @@ -400,7 +403,7 @@ bool IRrecv::decodeBangOlufsen() { } } } else { -#endif +#endif // !defined(ENABLE_BEO_WITHOUT_FRAME_GAP) /* * Decode header / data diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 6c7aefeb0..3b67e80ad 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -187,6 +187,9 @@ void IRsend::sendPronto_P(const char *str, int_fast8_t aNumberOfRepeats) { } #endif +/* + * Copy flash data to ram buffer in stack + */ void IRsend::sendPronto(const __FlashStringHelper *str, int_fast8_t aNumberOfRepeats) { size_t len = strlen_P(reinterpret_cast(str)); char work[len + 1]; diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 4bb12a4d5..267fe6ca8 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -74,7 +74,9 @@ // Here https://forum.arduino.cc/t/klimaanlage-per-ir-steuern/1051381/10 the address (0xB24D) is also 8 bits and then 8 inverted bits // // Here https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 -// Address is 8 bit + same 8 bit if data is 8 bit and ~8 bit. +// Address is 8 bit + same 8 bit if command is 8 bit and ~8 bit. +// +// So we assume 8 bit address, if command is 8 bit and ~8 bit! // // IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:8,~F:8,1,^110)+ ==> 8 bit + 8 bit inverted data - Samsung32 // IRP notation: {38k,5553}<1,-1|1,-3>(8,-8,D:8,S:8,F:16,1,^110)+ ==> 16 bit data - still Samsung32 @@ -99,6 +101,7 @@ #define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down. #define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess +// 19 byte RAM struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL }; @@ -160,17 +163,18 @@ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNu /** * Here we send Samsung32 * If we get a command < 0x100, we send command and then ~command - * If we get an address < 0x100, we send address and then address again, this makes it flipper IRDB compatible + * If we get an address < 0x100, we send 8 bit address and then the same 8 bit address again, this makes it flipper IRDB compatible * !!! Be aware, that this is flexible, but makes it impossible to send e.g. 0x0042 as 16 bit value!!! + * To force send 16 bit address, use: sendSamsung16BitAddressAndCommand(). * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent */ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { LongUnion tSendValue; if (aAddress < 0x100) { - // This makes it flipper IRDB compatible + // This makes it flipper IRDB compatible: // https://github.com/flipperdevices/flipperzero-firmware/blob/master/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c#L18 - // Duplicate address byte, if data is 8 bit and 8 bit inverted and address is 8bit + // Duplicate address byte, if address is only 8 bit tSendValue.UBytes[1] = aAddress; tSendValue.UBytes[0] = aAddress; } else { @@ -190,6 +194,23 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } +/** + * Maybe no one needs it in the wild... + * As above, but we are able to send e.g. 0x0042 as 16 bit address + * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent + */ +void IRsend::sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { + + LongUnion tSendValue; + // send 16 bit address + tSendValue.UWords[0] = aAddress; + // Send 8 command bits and then 8 inverted command bits LSB first + tSendValue.UBytes[2] = aCommand; + tSendValue.UBytes[3] = ~aCommand; + + sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); +} + /** * Maybe no one needs it in the wild... * As above, but we are able to send e.g. 0x0042 as 16 bit address @@ -205,7 +226,6 @@ void IRsend::sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aComm sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } - /** * Here we send Samsung48 * We send 2 x (8 bit command and then ~command) @@ -241,6 +261,11 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu #endif } +/* + * We cannot decode frames with 8 command bits and then 8 inverted command bits LSB and 16 bit address, + * because in this case we always assume 8 bit address. + * This is, because we did not see 8 bit command and real 16 bit address in the wild. + */ bool IRrecv::decodeSamsung() { // Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark @@ -322,11 +347,11 @@ bool IRrecv::decodeSamsung() { * Samsung32 */ if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { - // 8 bit command (and address) protocol + // 8 bit command protocol -> assume 8 bit address decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit - decodedIRData.address = tValue.UByte.MidLowByte; // assume LowByte == MidLowByte + decodedIRData.address = tValue.UByte.LowByte; // assume LowByte == MidLowByte } else { - // 16 bit command protocol + // 16 bit command protocol, address is filled above with the 16 bit value decodedIRData.command = tValue.UWord.HighWord; // first 16 bit } decodedIRData.numberOfBits = SAMSUNG_BITS; From a28b94fabec6fe86ecbb1594e0602e670bc03219 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 15 May 2024 22:11:57 +0200 Subject: [PATCH 041/133] Added macro USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN --- README.md | 33 +++++++++++++++++---------------- examples/SendDemo/SendDemo.ino | 3 ++- src/IRSend.hpp | 5 +++++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 779107c48..253b2d830 100644 --- a/README.md +++ b/README.md @@ -711,24 +711,25 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| -| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. | -| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. | -| `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | +| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. | +| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. | +| `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | | `DECODE_STRICT_CHECKS` | disabled | Check for additional required characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. | | `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | -| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | -| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | -| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | -| `IR_SEND_PIN` | disabled | If specified, 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). | -| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | -| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | -| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | -| `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | -| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | -| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | -| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | -| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. | +| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | +| `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | +| `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | +| `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | +| `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the advantage of more exact PWM generation, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the disadvantage of using a hardware timer, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | +| `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | +| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | +| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | +| `USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN` | disabled | Only if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. | +| `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | +| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | +| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | +| `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | +| `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. | | `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` | 25 | Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. | | `DEBUG` | disabled | Enables lots of lovely debug output. | | `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. | diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 28e108288..68be9fff4 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -40,8 +40,9 @@ //#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition +//#define USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN // Simulate an active high receiver signal instead of an active low signal. +//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! //#define NO_LED_FEEDBACK_CODE // Saves 566 bytes program memory -//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! //#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below #include diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 5fefca80c..532ac03f0 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -968,7 +968,10 @@ void IRsend::mark(uint16_t aMarkMicros) { * Here we generate no carrier PWM, just simulate an active low receiver signal. */ # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN) + // Here we have no hardware supported Open Drain outputs, so we must mimicking it pinModeFast(sendPin, OUTPUT); // active state for mimicking open drain +# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN) + digitalWriteFast(sendPin, HIGH); // Set output to active high. # else digitalWriteFast(sendPin, LOW); // Set output to active low. # endif @@ -1114,6 +1117,8 @@ void IRsend::IRLedOff() { # if defined(USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN) && !defined(OUTPUT_OPEN_DRAIN) digitalWriteFast(sendPin, LOW); // prepare for all next active states. pinModeFast(sendPin, INPUT);// inactive state for open drain +# elif defined(USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN) + digitalWriteFast(sendPin, LOW); // Set output to inactive low. # else digitalWriteFast(sendPin, HIGH); // Set output to inactive high. # endif From 60a37105976f11f2a21e5d0ac15064498b55501d Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 24 May 2024 16:23:22 +0200 Subject: [PATCH 042/133] Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) and sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent. --- README.md | 11 +++++++++-- changelog.md | 4 ++++ examples/SimpleSender/SimpleSender.ino | 12 ++++++++++++ src/IRremoteInt.h | 2 ++ src/ir_Samsung.hpp | 5 ++++- src/ir_Sony.hpp | 5 ++++- 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 253b2d830..b718627fe 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [How we decode signals](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-we-decode-signals) - [NEC encoding diagrams](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#nec-encoding-diagrams) - [Quick comparison of 5 Arduino IR receiving libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries) +- [History](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/changelog.md) - [Useful links](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#useful-links) - [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md) - [License](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#license) @@ -158,7 +159,7 @@ If IR_SEND_PIN is not defined (before the line `#include `) you mu - Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L90-L101). - Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`. -- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data for **NEC** and **JVC** were renamed to `sendNECMSB`, and `sendJVCMSB()`. The old `sendSAMSUNG()` and `sendSony()` MSB functions are still available. The old MSB version of `sendPanasonic()` function was deleted, since it had bugs nobody recognized.
+- 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). ### Example @@ -231,6 +232,8 @@ Example: If you **read the first binary sequence backwards** (right to left), you get the second sequence. You may use `bitreverseOneByte()` or `bitreverse32Bit()` for this. +Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`. +
# Errors with using the 4.x versions for old tutorials @@ -407,7 +410,7 @@ Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms Keep in mind, that **there is no delay after the last sent mark**. If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding. -The old send*Raw() functions for sending like e.g. `IrSender.sendNECRaw(0xE61957A8,2)` are kept for backward compatibility to **(old)** tutorials and unsupported as well as error prone. +Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`. ## Send pin Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
@@ -953,6 +956,8 @@ 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 - [List of public IR code databases](http://www.harctoolbox.org/IR-resources.html) - [LIRC database](http://lirc-remotes.sourceforge.net/remotes-table.html) @@ -965,6 +970,8 @@ It is dated from **24.06.2022** and updated 10/2023. If you have complains about - The original blog post of Ken Shirriff [A Multi-Protocol Infrared Remote Library for the Arduino](http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html) - [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf) +# [Contributors](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Contributors.md) + # License Up to the version 2.7.0, the License is GPLv2. From the version 2.8.0, the license is the MIT license. diff --git a/changelog.md b/changelog.md index cebf37121..5c6abb50e 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.3.2 +- Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. +- Added sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent. + # 4.3.1 - Fixed overflow bug for rawlen > 254. - Removed deprecated sendPulseDistance... functions with parameter aSendStopBit. diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index bf226cb07..553053633 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -68,6 +68,18 @@ void loop() { // Receiver output for the first loop must be: Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 (32 bits) IrSender.sendNEC(0x00, sCommand, sRepeats); + /* + * If you want to send a raw HEX value directly like e.g. 0xCB340102 you must use sendNECRaw() + */ +// Serial.println(F("Send 32 bit LSB 0xCB340102 with NECRaw()")); +// IrSender.sendNECRaw(0xCB340102, sRepeats); + + /* + * If you want to send an "old" MSB HEX value used by IRremote versions before 3.0 like e.g. 0x40802CD3 you must use sendNECMSB() + */ +// Serial.println(F("Send old 32 bit MSB 0x40802CD3 with sendNECMSB()")); +// IrSender.sendNECMSB(0x40802CD3, 32, sRepeats); + /* * Increment send values */ diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 07b9380ff..6a1257925 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -599,6 +599,8 @@ class IRsend { void sendSharp(uint16_t address, uint16_t command); void sendSAMSUNG(unsigned long data, int nbits); __attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung()."))); + void sendSamsungMSB(unsigned long data, int nbits); + void sendSonyMSB(unsigned long data, int nbits); void sendSony(unsigned long data, int nbits) __attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats)."))); diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 267fe6ca8..154b74b21 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -407,7 +407,7 @@ bool IRrecv::decodeSAMSUNG(decode_results *aResults) { } // Old version with MSB first -void IRsend::sendSAMSUNG(unsigned long data, int nbits) { +void IRsend::sendSamsungMSB(unsigned long data, int nbits) { // Set IR carrier frequency enableIROut (SAMSUNG_KHZ); @@ -419,6 +419,9 @@ void IRsend::sendSAMSUNG(unsigned long data, int nbits) { sendPulseDistanceWidthData(SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST); } +void IRsend::sendSAMSUNG(unsigned long data, int nbits) { + sendSamsungMSB(data, nbits); +} /** @}*/ #if defined(LOCAL_DEBUG) diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index 9f0d0c2ff..c757e30e1 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -213,7 +213,7 @@ bool IRrecv::decodeSonyMSB(decode_results *aResults) { /** * Old version with MSB first data */ -void IRsend::sendSony(unsigned long data, int nbits) { +void IRsend::sendSonyMSB(unsigned long data, int nbits) { // Set IR carrier frequency enableIROut (SONY_KHZ); @@ -224,6 +224,9 @@ void IRsend::sendSony(unsigned long data, int nbits) { // Old version with MSB first Data sendPulseDistanceWidthData(SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST); } +void IRsend::sendSony(unsigned long data, int nbits) { + sendSonyMSB(data, nbits); +} /** @}*/ #if defined(LOCAL_DEBUG) From e0ffb2ca0800860340469588ec028e0e84044f28 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 24 May 2024 19:10:11 +0200 Subject: [PATCH 043/133] Documentation --- .github/workflows/LibraryBuild.yml | 1 + README.md | 4 +++- examples/ReceiveAndSend/ReceiveAndSend.ino | 1 + .../ReceiveAndSendDistanceWidth.ino | 5 +++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index ab146aa92..6ed4e4012 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -82,6 +82,7 @@ jobs: include: - arduino-boards-fqbn: arduino:avr:uno build-properties: # the flags were put in compiler.cpp.extra_flags + ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 - arduino-boards-fqbn: arduino:avr:uno|DEBUG diff --git a/README.md b/README.md index b718627fe..2b0639151 100644 --- a/README.md +++ b/README.md @@ -611,7 +611,8 @@ If you do not know which protocol your IR transmitter uses, you have several cho # Examples for this library The examples are available at File > Examples > Examples from Custom Libraries / IRremote.
- 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. @@ -964,6 +965,7 @@ It is dated from **24.06.2022** and updated 10/2023. If you have complains about - [IRMP list of IR protocols](https://www.mikrocontroller.net/articles/IRMP_-_english#IR_Protocols) - [IRDB database for IR codes](https://github.com/probonopd/irdb/tree/master/codes) - [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols) +- [Good introduction to IR remotes by DroneBot Workshop](https://dronebotworkshop.com/ir-remotes/) - [IR Remote Control Theory and some protocols (upper right hamburger icon)](https://www.sbprojects.net/knowledge/ir/) - [Interpreting Decoded IR Signals (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html) - ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino) diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 45b139eb4..d7ce891af 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -14,6 +14,7 @@ * A button must be connected between the input SEND_BUTTON_PIN and ground. * A visible LED can be connected to STATUS_PIN to provide status. * + * See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSend_Code * * Initially coded 2009 Ken Shirriff http://www.righto.com * diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 93c6e8edb..e04f87030 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -16,6 +16,7 @@ * A button must be connected between the input SEND_BUTTON_PIN and ground. * A visible LED can be connected to STATUS_PIN to provide status. * + * See also https://dronebotworkshop.com/ir-remotes/#ReceiveAndSendDistanceWidth_Code * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * @@ -80,8 +81,8 @@ #define DELAY_BETWEEN_REPEATS_MILLIS 70 // Storage for the recorded code, pre-filled with NEC data -IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // address 0x12 command 0x34 -DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // NEC timing +IRRawDataType sDecodedRawDataArray[RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34 +DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing uint8_t sNumberOfBits = 32; bool sSendButtonWasActive; From f6e025583839cc218c6d3270c74edf04cf7eb5b3 Mon Sep 17 00:00:00 2001 From: Paliak <91493239+Paliak@users.noreply.github.com> Date: Sun, 26 May 2024 23:22:46 +0200 Subject: [PATCH 044/133] Fix callback code disable macro causing compilation error (#1231) * FIX: callback code disable macro causing compilation error --- src/IRReceive.hpp | 6 ++++-- src/IRremoteInt.h | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 7249942d1..3a563d44f 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -198,7 +198,7 @@ void IRReceiveTimerInterruptHandler() { // Flag up a read OverflowFlag; Stop the state machine irparams.OverflowFlag = true; irparams.StateForISR = IR_REC_STATE_STOP; -#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK +#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) /* * Call callback if registered (not NULL) */ @@ -224,7 +224,7 @@ void IRReceiveTimerInterruptHandler() { * Don't reset TickCounterForISR; keep counting width of next leading space */ irparams.StateForISR = IR_REC_STATE_STOP; -#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK +#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) /* * Call callback if registered (not NULL) */ @@ -335,12 +335,14 @@ void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) { pinModeFast(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32 } +#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) /** * Sets the function to call if a protocol message has arrived */ void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) { irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction; } +#endif /** * Start the receiving process. diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 6a1257925..d346d3cae 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -106,7 +106,7 @@ struct irparams_struct { uint8_t IRReceivePinMask; #endif volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is independent of state or resume(). -#if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK +#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP #endif bool OverflowFlag; ///< Raw buffer OverflowFlag occurred @@ -181,7 +181,10 @@ class IRrecv { IRrecv(uint_fast8_t aReceivePin); IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin); void setReceivePin(uint_fast8_t aReceivePinNumber); +#if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) void registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)); +#endif + /* * Stream like API */ From 97085428ddb84d5ce5a2d0959f8c98717e703a44 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 30 May 2024 00:30:36 +0200 Subject: [PATCH 045/133] Documentation --- .github/workflows/LibraryBuild.yml | 2 ++ README.md | 17 ++++++++++------- examples/ReceiveDemo/ReceiveDemo.ino | 1 + examples/UnitTest/UnitTest.ino | 2 +- src/private/IRTimer.hpp | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 6ed4e4012..1f2211c23 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -239,6 +239,7 @@ jobs: - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024 sketches-exclude: TinyReceiver # undefined reference to `TwoWire::onReceive(void (*)(int))' build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized @@ -246,6 +247,7 @@ jobs: - arduino-boards-fqbn: esp32:esp32:esp32c3 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json + arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024 sketches-exclude: TinyReceiver # undefined reference to `TwoWire::onReceive(void (*)(int))' build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized diff --git a/README.md b/README.md index 2b0639151..24fccf4de 100644 --- a/README.md +++ b/README.md @@ -386,7 +386,7 @@ On a long press, the **SamsungLG protocol** does not repeat its frame, it sends 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). +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.
@@ -531,12 +531,14 @@ 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 receivers -IRreceiver consists of one timer triggered function reading the digital IR signal value from one pin every 50 µs.
+## 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. -The IR receivers use an NPN transistor as output device with just a 30k resistor to VCC. -This is almost "open collector" and allows connecting of several output pins to one Arduino input pin.
-But keep in mind, that any weak / disturbed signal from one of the receivers will in turn also disturb a good signal from another one. +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. ## 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.
@@ -806,7 +808,8 @@ 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 **ESP32** `hw_timer_t` is used for receive interrupts and `ledc` channel 0 is used for gneating the IR PWM. +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. 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! diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index f9941e01d..71dc79a63 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -86,6 +86,7 @@ //#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active +//#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index c450152a8..43272bbb7 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -146,7 +146,7 @@ void setup() { #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 # if defined(IR_SEND_PIN_STRING) - Serial.println(F("at pin " IR_SEND_PIN_STRING)); + Serial.println(F("Send IR signals at pin " IR_SEND_PIN_STRING)); # else Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN))); # endif diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 335f33c68..0ad8b6185 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1414,7 +1414,7 @@ void timerEnableReceiveInterrupt() { timer1_attachInterrupt(&IRReceiveTimerInterruptHandler); // enables interrupt too } void timerDisableReceiveInterrupt() { - timer1_detachInterrupt(); // disables interrupt too } + timer1_detachInterrupt(); // disables interrupt too } void timerConfigForReceive() { From dee20d1a24506821fe679e04b816b0e900681538 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 10 Jun 2024 14:29:36 +0200 Subject: [PATCH 046/133] Bumped version to 4.3.2 Added ESP32 core 3.x error message --- .github/workflows/LibraryBuild.yml | 4 +-- changelog.md | 1 + examples/AllProtocolsOnLCD/ADCUtils.h | 9 +++++- examples/AllProtocolsOnLCD/ADCUtils.hpp | 28 +++++++++++++++---- .../ReceiverTimingAnalysis.ino | 2 ++ library.json | 2 +- library.properties | 2 +- src/IRVersion.h | 4 +-- src/private/IRTimer.hpp | 4 +++ 9 files changed, 43 insertions(+), 13 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 1f2211c23..be5dd8333 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -239,7 +239,7 @@ jobs: - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024 + 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: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized @@ -247,7 +247,7 @@ jobs: - arduino-boards-fqbn: esp32:esp32:esp32c3 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - arduino-platform: esp32:esp32@2.0.17 # latest 2.x version of 5/2024 + 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: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized diff --git a/changelog.md b/changelog.md index 5c6abb50e..0215b7b7f 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.3.2 - Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. - Added sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent. +- Added ESP32 core 3.x error message. # 4.3.1 - Fixed overflow bug for rawlen > 254. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index ce283c2f3..c40621787 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -101,6 +101,12 @@ #define ADC_GND_CHANNEL_MUX 15 #define ADC_CHANNEL_MUX_MASK 0x0F +#elif defined(__AVR_ATmega644P__) +#define ADC_TEMPERATURE_CHANNEL_MUX // not existent +#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E +#define ADC_GND_CHANNEL_MUX 0x1F +#define ADC_CHANNEL_MUX_MASK 0x0F + #elif defined(__AVR_ATmega32U4__) #define ADC_TEMPERATURE_CHANNEL_MUX 0x27 #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E @@ -208,7 +214,8 @@ void resetCounterForVCCUndervoltageMultipleTimes(); bool isVCCUndervoltage(); bool isVCCEmergencyUndervoltage(); bool isVCCOvervoltage(); -bool isVCCOvervoltageSimple(); +bool isVCCOvervoltageSimple(); // Version using readVCCVoltageMillivoltSimple() +bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimple() #endif // defined(__AVR__) ... diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 0cff66eb7..b5e04f5b3 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -715,6 +715,7 @@ void resetCounterForVCCUndervoltageMultipleTimes() { * Raw reading of 1.1 V is 221 at 5.1 V. * Raw reading of 1.1 V is 214 at 5.25 V (+5 %). * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). + * Raw reading of 1.1 V is 1126000 / VCC_MILLIVOLT * @return true if 5 % overvoltage reached */ bool isVCCOvervoltage() { @@ -726,6 +727,21 @@ bool isVCCOvervoltageSimple() { return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT); } +// Version not using readVCCVoltageMillivoltSimple() +bool isVCCTooHighSimple() { + ADMUX = ADC_1_1_VOLT_CHANNEL_MUX | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE); +// ADCSRB = 0; // Only active if ADATE is set to 1. +// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE128); // 128 -> 104 microseconds per ADC conversion at 16 MHz --- Arduino default +// wait for single conversion to finish + loop_until_bit_is_clear(ADCSRA, ADSC); + +// Get value + uint16_t tRawValue = ADCL | (ADCH << 8); + + return tRawValue < 1126000 / VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT; +} + /* * Temperature sensor is enabled by selecting the appropriate channel. * Different formula for 328P and 328PB! @@ -737,18 +753,18 @@ float getCPUTemperatureSimple(void) { return 0.0; #else // use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-( - uint16_t tTempRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2); + uint16_t tTemperatureRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2); #if defined(LOCAL_DEBUG) Serial.print(F("TempRaw=")); - Serial.println(tTempRaw); + Serial.println(tTemperatureRaw); #endif #if defined(__AVR_ATmega328PB__) - tTempRaw -= 245; - return (float)tTempRaw; + tTemperatureRaw -= 245; + return (float)tTemperatureRaw; #else - tTempRaw -= 317; - return (float) tTempRaw / 1.22; + tTemperatureRaw -= 317; + return (float) tTemperatureRaw / 1.22; #endif #endif } diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index 410b3fde7..b35af6820 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -42,7 +42,9 @@ #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) +#if !(defined(EICRA) && defined(EIFR) && defined(EIMSK)) void measureTimingISR(void); +#endif void setup() { diff --git a/library.json b/library.json index 0e688c865..9f57770c9 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git" }, - "version": "4.3.1", + "version": "4.3.2", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index 69d5084fd..865e5c829 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.3.1 +version=4.3.2 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRVersion.h b/src/IRVersion.h index 5d5bfde39..0ad8d7bfa 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.3.1" +#define VERSION_IRREMOTE "4.3.2" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 3 -#define VERSION_IRREMOTE_PATCH 1 +#define VERSION_IRREMOTE_PATCH 2 /* * Macro to convert 3 version parts into an integer diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 0ad8b6185..d5eb42ace 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1434,6 +1434,10 @@ void timerConfigForReceive() { * so it is recommended to always define SEND_PWM_BY_TIMER **********************************************************/ #elif defined(ESP32) +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +#error This library does not work with ESP32 core 3.x. You are kindly invited to port and document the code to 3.x, to fix this problem! +# endif + // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() From 3a11811ab6b85e497b7e926475157b04424cd119 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 11 Jun 2024 15:33:53 +0200 Subject: [PATCH 047/133] sendNEC() and sendNEC2() now accepts 16 bit command to better map to NEXext protocol found in IRDB databases. ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. --- changelog.md | 4 ++ .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 4 +- src/IRReceive.hpp | 47 ++++++++++++++++++- src/IRremoteInt.h | 7 ++- src/ir_DistanceWidthProtocol.hpp | 40 +++++++++++----- src/ir_NEC.hpp | 42 ++++++++++------- 6 files changed, 109 insertions(+), 35 deletions(-) diff --git a/changelog.md b/changelog.md index 0215b7b7f..2bfd2a8cb 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.3.3 +- sendNEC() and sendNEC2() now accepts 16 bit command to better map to NEXext protocol found in IRDB databases. +- ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. + # 4.3.2 - Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. - Added sendSamsungMSB(unsigned long data, int nbits) as a clone of sendSAMSUNG(unsigned long data, int nbits) to be more consistent. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 9a9e9cc34..b27eb7be5 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -40,9 +40,11 @@ # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) #define RAW_BUFFER_LENGTH 180 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 520 +#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # else #define RAW_BUFFER_LENGTH 750 +#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 400 // The decoder accepts mark or space durations up to 400 * 50 (MICROS_PER_TICK) = 20 milliseconds # endif #endif diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 3a563d44f..b6a5f4734 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -856,7 +856,7 @@ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a * Static variables for the getBiphaselevel function */ uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array -uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. +uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. uint16_t sBiphaseTimeUnit; @@ -1276,6 +1276,51 @@ void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInf aSerial->print(aDistanceWidthTimingInfo->ZeroSpaceMicros); } +/* + * Get maximum of mark ticks in rawDataPtr. + * Skip leading start and trailing stop bit. + */ +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]; + if (tMaximumTick < tTick) { + tMaximumTick = tTick; + } + } + return tMaximumTick; +} +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]; + if (tMaximumTick < tTick) { + tMaximumTick = tTick; + } + } + return tMaximumTick; +} + +/* + * The optimizing compiler internally generates this function, if getMaximumMarkTicksFromRawData() and getMaximumSpaceTicksFromRawData() is used. + */ +uint8_t IRrecv::getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark) { + uint8_t tMaximumTick = 0; + IRRawlenType i; + if (aSearchSpaceInsteadOfMark) { + i = 4; + } else { + i = 3; + } + for (; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit. + auto tTick = decodedIRData.rawDataPtr->rawbuf[i]; + if (tMaximumTick < tTick) { + tMaximumTick = tTick; + } + } + return tMaximumTick; +} + uint32_t IRrecv::getTotalDurationOfRawData() { uint16_t tSumOfDurationTicks = 0; diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index d346d3cae..59297ba8d 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -225,6 +225,9 @@ class IRrecv { void printIRResultMinimal(Print *aSerial); void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true); void printIRResultAsCVariables(Print *aSerial); + uint8_t getMaximumMarkTicksFromRawData(); + uint8_t getMaximumSpaceTicksFromRawData(); + uint8_t getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark); uint32_t getTotalDurationOfRawData(); /* @@ -524,8 +527,8 @@ class IRsend { void sendNECRepeat(); uint32_t computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aCommand); - void sendNEC(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); - void sendNEC2(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); + void sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); + void sendNEC2(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendNECRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats = NO_REPEATS); // NEC variants void sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 258de8246..67233901a 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -2,7 +2,10 @@ * ir_DistanceWidthProtocol.hpp * * Contains only the decoder functions for universal pulse width or pulse distance protocols! - * The send functions are used by almost all protocols and therefore in IRSend.hh. + * The send functions are used by almost all protocols and are therefore located in IRSend.hpp. + * + * If RAM is not more than 2k, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds + * to save RAM space, otherwise it accepts durations up to 10 ms. * * This decoder tries to decode a pulse distance or pulse distance width with constant period (or pulse width - not enabled yet) protocol. * 1. Analyze all space and mark length @@ -31,7 +34,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -65,8 +68,13 @@ //#define LOCAL_DEBUG // This enables debug output only for this file #endif -// accept durations up to 50 * 50 (MICROS_PER_TICK) 2500 microseconds -#define DURATION_ARRAY_SIZE 50 +#if !defined(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) +# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 50 // To save program space, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds +# else +#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds +# endif +#endif // Switch the decoding according to your needs //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // If active, it resembles LG, otherwise LSB first as most other protocols e.g. NEC and Kaseikyo/Panasonic @@ -148,9 +156,15 @@ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIn * 2. Decide if we have an pulse width or distance protocol * 3. Try to decode with the mark and space data found in step 1 * No data and address decoding, only raw data as result. + * + * calloc() version is 700 bytes larger :-( */ bool IRrecv::decodeDistanceWidth() { - uint8_t tDurationArray[DURATION_ARRAY_SIZE]; // For up to 49 ticks / 2450 us + /* + * 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 + */ + uint8_t tDurationArray[DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE]; /* * Accept only protocols with at least 8 bits @@ -164,16 +178,16 @@ bool IRrecv::decodeDistanceWidth() { } // Reset duration array - memset(tDurationArray, 0, DURATION_ARRAY_SIZE); + memset(tDurationArray, 0, DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE); uint8_t tIndexOfMaxDuration = 0; /* - * Count number of mark durations up to 49 ticks. Skip leading start and trailing stop bit. + * 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]; - if (tDurationTicks < DURATION_ARRAY_SIZE) { - tDurationArray[tDurationTicks]++; // count duration if less than DURATION_ARRAY_SIZE (50) + 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; } @@ -183,7 +197,7 @@ bool IRrecv::decodeDistanceWidth() { Serial.print(F("Mark ")); Serial.print(tDurationTicks * MICROS_PER_TICK); Serial.print(F(" is longer than maximum ")); - Serial.print(DURATION_ARRAY_SIZE * MICROS_PER_TICK); + Serial.print(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE * MICROS_PER_TICK); Serial.print(F(" us. Index=")); Serial.println(i); #endif @@ -211,7 +225,7 @@ bool IRrecv::decodeDistanceWidth() { } // Reset duration array - memset(tDurationArray, 0, DURATION_ARRAY_SIZE); + memset(tDurationArray, 0, DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE); /* * Count number of space durations. Skip leading start and trailing stop bit. @@ -219,7 +233,7 @@ bool IRrecv::decodeDistanceWidth() { tIndexOfMaxDuration = 0; for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) { auto tDurationTicks = decodedIRData.rawDataPtr->rawbuf[i]; - if (tDurationTicks < DURATION_ARRAY_SIZE) { + if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; if (tIndexOfMaxDuration < tDurationTicks) { tIndexOfMaxDuration = tDurationTicks; @@ -230,7 +244,7 @@ bool IRrecv::decodeDistanceWidth() { Serial.print(F("Space ")); Serial.print(tDurationTicks * MICROS_PER_TICK); Serial.print(F(" is longer than maximum ")); - Serial.print(DURATION_ARRAY_SIZE * MICROS_PER_TICK); + Serial.print(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE * MICROS_PER_TICK); Serial.print(F(" us. Index=")); Serial.println(i); #endif diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index e51eda676..8d59d06b9 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -71,10 +71,10 @@ */ // 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 16 independent address and command bits: +// NEC: LSB first, (or ) . +// ONKYO: like NEC but force to 16 independent address and 16 bit command bits: // Standard NEC sends a special fixed repeat frame. -// NEC2 sends the same full frame after the 110 ms. I have a DVD remote with NEC2. +// NEC2: like NEC, but for repeat, the same full frame is sent after the 110 ms. I have a DVD remote with NEC2. // NEC and NEC 2 only differ in the repeat frames, so the protocol can only be detected correctly after the first repeat. // PIONEER (not implemented) is NEC2 with 40 kHz // @@ -150,6 +150,13 @@ void sendNECSpecialRepeat() { IrSender.mark(NEC_BIT_MARK); // + 560 } +/** + * Convert 16 bit address and 16 bit command to 32 bit NECRaw data + * If we get a command < 0x100, we send command and then ~command + * If we get an address < 0x100, we send 8 bit address and then ~address + * !!! Be aware, that this is flexible, but makes it impossible to send e.g. 0x0042 as 16 bit value!!! + * To force send 16 bit address, use: sendOnkyo(). + */ uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aCommand) { LongUnion tRawData; @@ -173,21 +180,11 @@ uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aComma * There is NO delay after the last sent repeat! * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ -void IRsend::sendNEC(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { +void IRsend::sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth(&NECProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); } -/* - * NEC2 Send frame and repeat the frame for each requested repeat - * There is NO delay after the last sent repeat! - * @param aNumberOfRepeats If < 0 then nothing is sent. - */ -void IRsend::sendNEC2(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&NEC2ProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); -} - -/* - * Repeat commands should be sent in a 110 ms raster. +/** * There is NO delay after the last sent repeat! * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). @@ -196,8 +193,17 @@ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumber sendPulseDistanceWidth(&NECProtocolConstants, (uint32_t) aCommand << 16 | aAddress, NEC_BITS, aNumberOfRepeats); } -/* - * Repeat commands should be sent in a 110 ms raster. +/** + * NEC2 Send frame !!! and repeat the frame for each requested repeat !!! + * There is NO delay after the last sent repeat! + * @param aNumberOfRepeats If < 0 then nothing is sent. + */ +void IRsend::sendNEC2(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { + sendPulseDistanceWidth(&NEC2ProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); +} + +/** + * Apple: Send NEC with fixed 16 bit Apple address 0x87EE. * There is NO delay after the last sent repeat! * https://en.wikipedia.org/wiki/Apple_Remote * https://gist.github.com/darconeous/4437f79a34e3b6441628 @@ -217,7 +223,7 @@ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberO sendPulseDistanceWidth(&NECProtocolConstants, tRawData.ULong, NEC_BITS, aNumberOfRepeats); } -/* +/** * Sends NEC protocol * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). From bdb51046727566188f3ba4c89ba1b85082644fa0 Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 11 Jun 2024 21:46:09 +0200 Subject: [PATCH 048/133] Improved examples AllProtocolsOnLCD, UnitTest and SimpleReceiver --- README.md | 32 ++- changelog.md | 3 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 33 ++- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 3 +- examples/ControlRelay/ControlRelay.ino | 6 +- examples/ControlRelay/PinDefinitionsAndMore.h | 3 +- .../IRDispatcherDemo/IRDispatcherDemo.ino | 12 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 3 +- .../IRremoteExtensionClass.cpp | 4 +- .../IRremoteExtensionTest.ino | 9 +- .../PinDefinitionsAndMore.h | 3 +- examples/IRremoteInfo/IRremoteInfo.ino | 6 +- examples/MicroGirs/MicroGirs.ino | 25 +- examples/MicroGirs/PinDefinitionsAndMore.h | 3 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 3 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 8 +- .../PinDefinitionsAndMore.h | 3 +- .../ReceiveAndSendDistanceWidth.ino | 6 +- .../PinDefinitionsAndMore.h | 3 +- .../ReceiveAndSendHob2Hood.ino | 6 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 3 +- examples/ReceiveDemo/ReceiveDemo.ino | 13 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 3 +- examples/ReceiveDump/ReceiveDump.ino | 10 +- .../PinDefinitionsAndMore.h | 3 +- .../ReceiveOneAndSendMultiple.ino | 22 +- .../ReceiverTimingAnalysis.ino | 60 ++--- .../SendAndReceive/PinDefinitionsAndMore.h | 3 +- examples/SendAndReceive/SendAndReceive.ino | 6 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 3 +- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 6 +- examples/SendDemo/PinDefinitionsAndMore.h | 3 +- examples/SendDemo/SendDemo.ino | 35 ++- .../PinDefinitionsAndMore.h | 3 +- .../SendLGAirConditionerDemo.ino | 7 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 3 +- examples/SendProntoDemo/SendProntoDemo.ino | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 3 +- examples/SendRawDemo/SendRawDemo.ino | 6 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 3 +- examples/SimpleReceiver/SimpleReceiver.ino | 3 + .../PinDefinitionsAndMore.h | 3 +- .../SimpleReceiverWithCallback.ino | 3 + examples/SimpleSender/PinDefinitionsAndMore.h | 3 +- examples/SimpleSender/SimpleSender.ino | 2 + examples/TinyReceiver/PinDefinitionsAndMore.h | 3 +- examples/TinyReceiver/TinyReceiver.ino | 6 +- examples/TinySender/PinDefinitionsAndMore.h | 3 +- examples/TinySender/TinySender.ino | 2 + examples/UnitTest/PinDefinitionsAndMore.h | 3 +- examples/UnitTest/UnitTest.ino | 115 ++++---- examples/UnitTest/UnitTest.log | 251 ++++++++---------- examples/UnitTest/UnitTest_64bit.log | 226 ++++++++-------- src/IRProtocol.h | 11 +- src/IRReceive.hpp | 28 +- src/IRremoteInt.h | 24 +- src/private/IRTimer.hpp | 2 +- 57 files changed, 575 insertions(+), 484 deletions(-) diff --git a/README.md b/README.md index 24fccf4de..cf30f46bd 100644 --- a/README.md +++ b/README.md @@ -47,12 +47,14 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols) * [Unknown protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#unknown-protocol) - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) + * [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) + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) - [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) - [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) - * [Receiving stops after analogWrite() or tone() or after running a motor.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor) + * [Receiving stops after analogWrite() or tone() or after running a motor](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor) + * [Receiving sets overflow flag](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-sets-overflow-flag) * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc) * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library) * [Multiple IR receiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver) @@ -329,7 +331,7 @@ Check it with e.g. `if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)` | IRDATA_FLAGS_PARITY_FAILED | The current (autorepeat) frame violated parity check. | | IRDATA_FLAGS_TOGGLE_BIT | Is set if RC5 or RC6 toggle bit is set. | | IRDATA_FLAGS_EXTRA_INFO | There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID, or in decodedRawDataArray). | -| IRDATA_FLAGS_WAS_OVERFLOW | irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag. | +| IRDATA_FLAGS_WAS_OVERFLOW | Too many marks and spaces for the specified `RAW_BUFFER_LENGTH`. To avoid endless flagging of overflow, irparams.rawlen is set to 0 in this case. | | IRDATA_FLAGS_IS_MSB_FIRST | This value is mainly determined by the (known) protocol. | #### To access the **RAW data**, use: @@ -402,9 +404,6 @@ If you are uncertain about the numbers of repeats to use for sending, **3** is a If you have enabled `DECODE_DISTANCE_WIDTH`, the code printed by `printIRSendUsage()` **differs between 8 and 32 bit platforms**, so it is best to run the receiving program on the same platform as the sending program. -The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**. Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* is the **command parameter** for the **new structured functions** with address, command and repeat-count parameters like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
-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. - **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**. @@ -412,6 +411,13 @@ If you handle the sending of repeat frames by your own, you must insert sensible Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`. +## 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. + +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. + ## Send pin Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
On **ESP32** ledc channel 0 is used for gereating the IR PWM.
@@ -517,6 +523,12 @@ Be aware that the hardware timer used for receiving should not be used for `anal 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()`. +## 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. +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. @@ -581,10 +593,12 @@ uint32_t tRawData[] = { 0xB02002, 0xA010 }; IrSender.sendPulseDistance(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, false, 0, 0); ``` You can send it with calling sendPulseDistanceWidthData() twice, once for the first 32 bit and next for the remaining 24 bits.
-**The PulseDistance or PulseWidth decoders just decode a timing steam to a bit stream**. +**The PulseDistance or PulseWidth decoders just decode a timing stream to a bit stream**. They can not put any semantics like address, command or checksum on this bitstream, since it is no known protocol. But the bitstream is way more readable, than a timing stream. This bitstream is read **LSB first by default**. -If this does not suit you for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L48). +If this does not suit you for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#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. @@ -655,6 +669,7 @@ Record and **play back last received IR signal** at button press. IR frames of k #### ReceiveAndSendDistanceWidth 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. @@ -717,13 +732,14 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| -| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. | +| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input 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. | | `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. | | `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | | `DECODE_STRICT_CHECKS` | disabled | Check for additional required characteristics of protocol timing like length of mark for a constant mark protocol, where space length determines the bit value. Requires up to 194 additional bytes of program memory. | | `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | | `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
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). | diff --git a/changelog.md b/changelog.md index 2bfd2a8cb..c8d360a81 100644 --- a/changelog.md +++ b/changelog.md @@ -3,8 +3,9 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.3.3 -- sendNEC() and sendNEC2() now accepts 16 bit command to better map to NEXext protocol found in IRDB databases. +- sendNEC() and sendNEC2() now accepts 16 bit command to better map to NECext protocol found in IRDB databases. - ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. +- Improved examples AllProtocolsOnLCD, UnitTest and SimpleReceiver. # 4.3.2 - Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index b27eb7be5..922c356dc 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2023 Armin Joachimsmeyer + * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -135,7 +135,11 @@ void setup() { #endif Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -176,7 +180,7 @@ void setup() { #endif Serial.println(F(", raw data is always printed")); - // infos for receive + // Info for receive Serial.print(RECORD_GAP_MICROS); Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed")); Serial.print(MARK_EXCESS_MICROS); @@ -382,10 +386,11 @@ void printIRResultOnLCD() { } else { /* - * Print only if address has changed + * Protocol is know here + * Print address only if it has changed */ - if (sLastProtocolAddress != IrReceiver.decodedIRData.address) { - sLastProtocolAddress = IrReceiver.decodedIRData.address; + if (sLastProtocolAddress != IrReceiver.decodedIRData.address || IrReceiver.decodedIRData.protocol == PULSE_DISTANCE + || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) { myLCD.setCursor(0, 1); /* @@ -393,13 +398,21 @@ void printIRResultOnLCD() { */ # if defined(DECODE_DISTANCE_WIDTH) if (IrReceiver.decodedIRData.protocol == PULSE_DISTANCE || IrReceiver.decodedIRData.protocol == PULSE_WIDTH) { + sLastProtocolAddress = 4711; // To enforce next print of address myLCD.print(F("[0]=0x")); uint_fast8_t tAddressStringLength = myLCD.print(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX); printSpacesOnLCD(LCD_COLUMNS - tAddressStringLength); - sLastCommand = 0; // to trigger restoration of "C=" string - return; // no command here + sLastCommand = 0; // to trigger restoration of "C=" string, if another protocol is received + /* + * No command here! + */ + return; + } else { # endif + sLastProtocolAddress = IrReceiver.decodedIRData.address; +// Serial.print(F("Print address 0x")); +// Serial.println(IrReceiver.decodedIRData.address, HEX); myLCD.print(F("A=")); uint_fast8_t tAddressStringLength = printByteHexOnLCD(IrReceiver.decodedIRData.address); printSpacesOnLCD((LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength); @@ -432,6 +445,10 @@ void printIRResultOnLCD() { /* * Command data */ +// Serial.print(F("Print command 0x")); +// Serial.print(tCommand, HEX); +// Serial.print(F(" at ")); +// Serial.println(sLastCommandPrintPosition); myLCD.setCursor(sLastCommandPrintPosition, 1); printByteHexOnLCD(tCommand); diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ControlRelay/ControlRelay.ino b/examples/ControlRelay/ControlRelay.ino index ebf77089f..346b13b34 100644 --- a/examples/ControlRelay/ControlRelay.ino +++ b/examples/ControlRelay/ControlRelay.ino @@ -53,7 +53,11 @@ void setup() { pinMode(RELAY_PIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 88f72024d..fda2a2c57 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -109,7 +109,11 @@ void doTone2200(); void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 #if defined(ESP8266) @@ -163,8 +167,7 @@ void loop() { DELAY_AND_RETURN_IF_STOP(sBlinkDelay); } - if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000) - { + if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000) { //Short beep as remainder, if we did not receive any command in the last 2 minutes IRDispatcher.IRReceivedData.MillisOfLastCode += 120000; doTone1800(); @@ -173,7 +176,7 @@ void loop() { // delay(10); } -void doPrintMenu(){ +void doPrintMenu() { Serial.println(); Serial.println(F("Press 1 for tone 1800 Hz")); Serial.println(F("Press 2 for tone 2200 Hz")); @@ -231,7 +234,6 @@ void doLedBlink20times() { } } - void doTone1800() { #if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) irmp_tone(TONE_PIN, 1800, 200); diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 821c387b3..61462904c 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -41,8 +41,6 @@ #define RAW_BUFFER_LENGTH 180 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define RAW_BUFFER_LENGTH 600 -# else -#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -56,7 +54,7 @@ bool IRExtensionClass::decode() { } bool IRExtensionClass::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) { - return MyIrReceiver->printIRResultShort(aSerial,aPrintRepeatGap,aCheckForRecordGapsMicros); + return MyIrReceiver->printIRResultShort(aSerial, aPrintRepeatGap, aCheckForRecordGapsMicros); } void IRExtensionClass::resume() { diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index 7f37f1f14..7c6c3611f 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -38,8 +38,6 @@ #define RAW_BUFFER_LENGTH 180 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define RAW_BUFFER_LENGTH 600 -# else -#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -54,7 +52,11 @@ IRExtensionClass IRExtension(&IrReceiver); void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -63,7 +65,6 @@ void setup() { // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); - Serial.print(F("Ready to receive IR signals of protocols: ")); printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino index 22ae75fbb..34c207ad0 100644 --- a/examples/IRremoteInfo/IRremoteInfo.ino +++ b/examples/IRremoteInfo/IRremoteInfo.ino @@ -34,7 +34,11 @@ void dumpFooter(); void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index ad9cb182a..326d22e0b 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -191,8 +191,7 @@ String Tokenizer::getRest() { } String Tokenizer::getLine() { - if (index == invalidIndex) - return String(""); + if (index == invalidIndex) return String(""); int i = payload.indexOf('\n', index); String s = (i > 0) ? payload.substring(index, i) : payload.substring(index); @@ -201,16 +200,13 @@ String Tokenizer::getLine() { } String Tokenizer::getToken() { - if (index < 0) - return String(""); + if (index < 0) return String(""); int i = payload.indexOf(' ', index); String s = (i > 0) ? payload.substring(index, i) : payload.substring(index); index = (i > 0) ? i : invalidIndex; - if (index != invalidIndex) - if (index != invalidIndex) - while (payload.charAt(index) == ' ') - index++; + if (index != invalidIndex) if (index != invalidIndex) while (payload.charAt(index) == ' ') + index++; return s; } @@ -254,13 +250,10 @@ static inline unsigned hz2khz(frequency_t hz) { */ static void sendRaw(const microseconds_t intro[], unsigned lengthIntro, const microseconds_t repeat[], unsigned lengthRepeat, const microseconds_t ending[], unsigned lengthEnding, frequency_t frequency, unsigned times) { - if (lengthIntro > 0U) - IrSender.sendRaw(intro, lengthIntro, hz2khz(frequency)); - if (lengthRepeat > 0U) - for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++) - IrSender.sendRaw(repeat, lengthRepeat, hz2khz(frequency)); - if (lengthEnding > 0U) - IrSender.sendRaw(ending, lengthEnding, hz2khz(frequency)); + if (lengthIntro > 0U) IrSender.sendRaw(intro, lengthIntro, hz2khz(frequency)); + if (lengthRepeat > 0U) for (unsigned i = 0U; i < times - (lengthIntro > 0U); i++) + IrSender.sendRaw(repeat, lengthRepeat, hz2khz(frequency)); + if (lengthEnding > 0U) IrSender.sendRaw(ending, lengthEnding, hz2khz(frequency)); } #endif // TRANSMIT @@ -302,7 +295,7 @@ static void receive(Stream &stream) { void setup() { Serial.begin(BAUDRATE); while (!Serial) - ; // wait for serial port to connect. + ; // 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 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index d7ce891af..7fe00c342 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -79,8 +79,6 @@ #define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; # elif (defined(RAMEND) && RAMEND <= 0xAFF) || (defined(RAMSIZE) && RAMSIZE < 0xAFF) #define RAW_BUFFER_LENGTH 500 // 750 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; -# else -#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -120,7 +118,11 @@ void setup() { pinMode(SEND_BUTTON_PIN, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index e04f87030..ffe557ad8 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -91,7 +91,11 @@ void setup() { pinMode(SEND_BUTTON_PIN, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index 9bb6113c3..41e5703be 100644 --- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -74,7 +74,11 @@ const uint16_t *const Hob2HoodSendCommands[NUMBER_OF_HOB_TO_HOOD_COMMANDS] = { F void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 71dc79a63..1f0ce6f68 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -77,9 +77,8 @@ # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) #define RAW_BUFFER_LENGTH 180 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 -# else -#define RAW_BUFFER_LENGTH 750 +#define RAW_BUFFER_LENGTH 520 +#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # endif #endif @@ -114,7 +113,11 @@ void setup() { #endif Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -257,7 +260,7 @@ void loop() { void generateTone() { #if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). # if defined(ESP32) // ESP32 uses another timer for tone() - tone(TONE_PIN, 2200, 5); + tone(TONE_PIN, 2200, 8); # else IrReceiver.stopTimer(); // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too. tone(TONE_PIN, 2200, 8); diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index e36562548..198ef064e 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -69,7 +69,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); // Status message will be sent to PC at 9600 baud -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -89,7 +93,9 @@ void setup() { Serial.println(); Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!")); Serial.println(); - Serial.println(F("If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2 or SamsungLG, which is determined by the repeats")); + Serial.println( + F( + "If you receive protocol NEC, Samsung or LG, run also ReceiveDemo to check if your actual protocol is eventually NEC2 or SamsungLG, which is determined by the repeats")); Serial.println(); } diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index 33218ab85..28f5c2524 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -13,7 +13,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2022 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -44,7 +44,7 @@ // USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED // GND 4| |5 PB0 (0) IR Input // +----+ -/* SAUMSUMG REMOTE CODES (Model: BN59-01180A) +/* SAUMSUMG REMOTE CODES (Model: BN59-01180A) - Address is 0x07 * Power Button - 0x2 * Power Off - 0x98 * 1 - 0x4 @@ -92,7 +92,7 @@ // select only Samsung protocol for sending and receiving #define DECODE_SAMSUNG -#define ADDRESS_OF_SAMSUNG_REMOTE 0x0707 // The value you see as address in printIRResultShort() +#define ADDRESS_OF_SAMSUNG_REMOTE 0x07 // The value you see as address in printIRResultShort() #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #include @@ -104,7 +104,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -189,9 +193,9 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS; } -# if !defined(ESP32) - IrReceiver.stopTimer(); // ESP32 uses another timer for tone() -# endif +#if !defined(ESP32) // ESP32 uses another timer for tone(), so the receiver must not be stopped and restarted for it + IrReceiver.stopTimer(); +#endif if (millis() < tWaitTimeAfterBoot) { // division by 1000 and printing requires much (8%) program memory Serial.print(F("It is ")); @@ -217,9 +221,9 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { tone(TONE_PIN, 2200, 200); delay(200); -# if !defined(ESP32) +#if !defined(ESP32) IrReceiver.restartTimer(200000); // to compensate for 200 ms stop of receiver. This enables a correct gap measurement. -# endif +#endif Serial.println(F("Wait for \"not supported\" to disappear")); delay(2000); diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index b35af6820..c0efd284f 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -46,11 +46,14 @@ void measureTimingISR(void); #endif -void setup() -{ +void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -75,8 +78,7 @@ void setup() uint8_t ISREdgeCounter = 0; volatile uint32_t LastMicros; -struct timingStruct -{ +struct timingStruct { uint16_t minimum; uint8_t indexOfMinimum; uint16_t maximum; @@ -95,23 +97,19 @@ struct timingStruct LongSpace; /* * Compute minimum, maximum and average */ -void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue) -{ - if (aTimingStruct->SampleCount == 0) - { +void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue) { + if (aTimingStruct->SampleCount == 0) { // initialize values aTimingStruct->minimum = UINT16_MAX; aTimingStruct->maximum = 0; aTimingStruct->SumForAverage = 0; } - if (aTimingStruct->minimum > aValue) - { + if (aTimingStruct->minimum > aValue) { aTimingStruct->minimum = aValue; aTimingStruct->indexOfMinimum = aTimingStruct->SampleCount; } - if (aTimingStruct->maximum < aValue) - { + if (aTimingStruct->maximum < aValue) { aTimingStruct->maximum = aValue; aTimingStruct->indexOfMaximum = aTimingStruct->SampleCount; } @@ -122,8 +120,7 @@ void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue) } -void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) -{ +void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) { // if (aTimingStruct->LastPrintedCount != aTimingStruct->SampleCount) // { // aTimingStruct->LastPrintedCount = aTimingStruct->SampleCount; @@ -147,10 +144,8 @@ void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) // } } -void loop() -{ - if (Mark.SampleCount >= 32) - { +void loop() { + if (Mark.SampleCount >= 32) { /* * This check enables statistics for longer protocols like Kaseikyo/Panasonics */ @@ -163,8 +158,7 @@ void loop() #endif uint32_t tMicrosDelta = micros() - tLastMicros; - if (tMicrosDelta > 10000) - { + if (tMicrosDelta > 10000) { // NEC signal ended just now Serial.println(); printTimingValues(&Mark, "Mark "); @@ -218,41 +212,31 @@ void measureTimingISR() uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN); digitalWrite(LED_BUILTIN, !tInputLevel); - if (tMicrosDelta > 10000) - { + if (tMicrosDelta > 10000) { // gap > 10 ms detected, reset counter to first detected edge and initialize timing structures ISREdgeCounter = 1; LongSpace.SampleCount = 0; ShortSpace.SampleCount = 0; Mark.SampleCount = 0; - } - else - { + } else { ISREdgeCounter++; } /* * Skip header mark and space and first bit mark and space */ - if (ISREdgeCounter > 4) - { - if (tInputLevel != LOW) - { + if (ISREdgeCounter > 4) { + if (tInputLevel != LOW) { // Mark ended processTmingValue(&Mark, tMicrosDelta); // Serial.print('M'); - } - else - { + } else { // Space ended - if (tMicrosDelta > 1000) - { + if (tMicrosDelta > 1000) { // long space - logical 1 processTmingValue(&LongSpace, tMicrosDelta); Serial.print('1'); - } - else - { + } else { // short space - logical 0 processTmingValue(&ShortSpace, tMicrosDelta); Serial.print('0'); diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 669de50c5..9e99353dc 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -53,7 +53,11 @@ void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 22d32b929..a7eafb3d6 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -110,7 +110,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 68be9fff4..278b88a0d 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -52,8 +52,11 @@ 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_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif // Just to know which program is running on my Arduino @@ -337,6 +340,18 @@ void loop() { 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 MagiQuest")); + Serial.flush(); + IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address + delay(DELAY_AFTER_SEND); + + // Bang&Olufsen must be sent with 455 kHz +// Serial.println(F("Send Bang&Olufsen")); +// Serial.flush(); +// IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats); +// delay(DELAY_AFTER_SEND); + /* * Next example how to use the IrSender.write function */ @@ -349,13 +364,6 @@ void loop() { Serial.println(F("Send next protocols with IrSender.write")); Serial.flush(); - IRSendData.protocol = SAMSUNG; - Serial.print(F("Send ")); - Serial.println(getProtocolString(IRSendData.protocol)); - Serial.flush(); - IrSender.write(&IRSendData, sRepeats); - delay(DELAY_AFTER_SEND); - IRSendData.protocol = JVC; // switch protocol Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); @@ -379,17 +387,6 @@ void loop() { IrSender.write(&IRSendData, sRepeats); delay(DELAY_AFTER_SEND); - Serial.println(F("Send MagiQuest")); - Serial.flush(); - IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address - delay(DELAY_AFTER_SEND); - - // Bang&Olufsen must be sent with 455 kHz -// Serial.println(F("Send Bang&Olufsen")); -// Serial.flush(); -// IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats); -// delay(DELAY_AFTER_SEND); - IRSendData.protocol = BOSEWAVE; Serial.println(F("Send Bosewave with no address and 8 command bits")); Serial.flush(); diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index 5b73aee40..90511f282 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -67,7 +67,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -79,7 +83,6 @@ delay(4000); // To be able to connect Serial monitor after reset or power up and */ 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); MyLG_Aircondition.printMenu(&Serial); diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index 5f6ff2e30..d4893f033 100644 --- a/examples/SendProntoDemo/SendProntoDemo.ino +++ b/examples/SendProntoDemo/SendProntoDemo.ino @@ -60,7 +60,7 @@ IRsend irsend; 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/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index e19ed9a3c..9af3bc1f7 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -53,7 +53,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index b36e46a39..a5153f4ec 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -72,6 +72,9 @@ 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/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index 7a570a43e..c68518cc4 100644 --- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino +++ b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino @@ -77,6 +77,9 @@ 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 048395099..37d57d93a 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index 553053633..d73b37485 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -29,6 +29,8 @@ 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)); diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index ce6067cba..bad39fea2 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -81,7 +81,11 @@ void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 048395099..37d57d93a 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 4af49883b..7a1fb3432 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -54,6 +54,8 @@ 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 048395099..37d57d93a 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -230,7 +230,8 @@ void noTone(uint8_t aPinNumber){ #define IR_SEND_PIN 12 #define TONE_PIN 5 -#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED +// Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 43272bbb7..8bdcb44b1 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -41,8 +41,6 @@ #define RAW_BUFFER_LENGTH 180 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define RAW_BUFFER_LENGTH 200 // 600 is too much here, because then variables are overwritten. 500 is OK without Pronto and 200 is OK with Pronto -# else -#define RAW_BUFFER_LENGTH 750 # endif #endif @@ -122,7 +120,11 @@ void setup() { pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) + 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 @@ -379,16 +381,20 @@ void loop() { Serial.println(); Serial.println(); - Serial.println(F("Send NEC with 8 bit address")); + 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); checkReceive(sAddress & 0xFF, sCommand); - // + for (int8_t i = 0; i < sRepeats; i++) { - Serial.println(F("Repeat NEC frame for NEC2")); - Serial.flush(); - // if debug is enabled, printing time (50 ms) is too high anyway - delayMicroseconds(NEC_REPEAT_DISTANCE - 200); // 200 is just a guess + 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 + } IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); } @@ -718,6 +724,46 @@ void loop() { delay(DELAY_AFTER_SEND); #endif +#if defined(DECODE_BEO) + Serial.println(F("Send Bang&Olufsen")); + Serial.flush(); + IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0); +# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) + delay((RECORD_GAP_MICROS / 1000) + 1); + Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); + Serial.println(F("- Now print raw data and try to decode 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; + /* + * decode first part / AGC part of frame + */ + IrReceiver.decode(); // sets IrReceiver.decodedIRData.rawlen to 6 + 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 + Serial.println(); + Serial.println( + F( + "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode")); + IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; + IrReceiver.decodedIRData.rawDataPtr->rawlen = tOriginalRawlen - 6; + for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { + IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6]; + } +# endif + 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 */ @@ -727,6 +773,10 @@ void loop() { IRSendData.command = sCommand; IRSendData.flags = IRDATA_FLAGS_EMPTY; + Serial.println(F("Send next protocols with IrSender.write")); + Serial.println(); + Serial.flush(); + #if defined(DECODE_JVC) IRSendData.protocol = JVC; // switch protocol Serial.print(F("Send ")); @@ -741,16 +791,6 @@ void loop() { IRSendData.command = s16BitCommand; // LG support more than 8 bit command #endif -#if defined(DECODE_SAMSUNG) - IRSendData.protocol = SAMSUNG; - Serial.print(F("Send ")); - Serial.println(getProtocolString(IRSendData.protocol)); - Serial.flush(); - IrSender.write(&IRSendData, 0); - checkReceive(IRSendData.address & 0xFF, IRSendData.command); - delay(DELAY_AFTER_SEND); -#endif - #if defined(DECODE_LG) IRSendData.protocol = LG; Serial.print(F("Send ")); @@ -761,43 +801,6 @@ void loop() { delay(DELAY_AFTER_SEND); #endif -#if defined(DECODE_MAGIQUEST) - Serial.println(F("Send MagiQuest")); - Serial.flush(); - IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address - checkReceive(sAddress, s16BitCommand & 0x1FF); // we have 9 bit command - delay(DELAY_AFTER_SEND); -#endif - -#if defined(DECODE_BEO) - Serial.println(F("Send Bang&Olufsen")); - Serial.flush(); - IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, 0); -# if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) - delay((RECORD_GAP_MICROS / 1000) + 1); - Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); - Serial.println(F("- Now print raw data and try to decode it, which must fail!")); - IrReceiver.printIRResultRawFormatted(&Serial, true); - uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawlen; - IrReceiver.decodedIRData.rawlen = 6; - // decode first part of frame - IrReceiver.decode(); - IrReceiver.printIRResultShort(&Serial); - - // Remove trailing 6 entries for second decode try - Serial.println(); - Serial.println( - F( - "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode")); - IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; - for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { - IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6]; - } -# endif - checkReceive(sAddress & 0x0FF, sCommand); - delay(DELAY_AFTER_SEND); -#endif - #if defined(DECODE_BOSEWAVE) IRSendData.protocol = BOSEWAVE; Serial.println(F("Send Bosewave with no address and 8 command bits")); diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index d89d0a7b9..d9e61435b 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -528,134 +528,110 @@ rawData[36]: + 450 Sum: 23250 -Send JVC -Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first -Send with: IrSender.sendJVC(0xF1, 0x76, ); +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]: - -1037050 - +8400,-4150 - + 500,-1600 + 550,- 500 + 500,- 550 + 550,- 500 - + 550,-1550 + 550,-1550 + 500,-1600 + 550,-1550 - + 550,- 500 + 550,-1550 + 550,-1550 + 500,- 550 - + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 - + 550 -Sum: 40400 + -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 + + 250 +Sum: 105700 +Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first -Send Samsung -Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first -Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: - -1039800 - +4550,-4400 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 - + 650 -Sum: 69000 - -Send LG -Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first -Send with: IrSender.sendLG(0xF1, 0x9876, ); -rawData[60]: - -1054900 - +9000,-4150 - + 450,-1600 + 500,-1550 + 500,-1550 + 500,-1600 - + 500,- 550 + 500,- 550 + 500,- 550 + 500,-1550 - + 500,-1600 + 500,- 550 + 500,- 550 + 450,-1600 - + 500,-1600 + 500,- 550 + 500,- 550 + 500,- 550 - + 500,- 550 + 500,-1550 + 500,-1550 + 550,-1550 - + 500,- 550 + 500,-1550 + 500,-1600 + 500,- 550 - + 500,-1550 + 500,-1550 + 500,-1600 + 500,- 550 - + 500 -Sum: 59350 +- 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, ); +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 Send MagiQuest -Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first -Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -1049950 - + 250,- 850 + 250,- 900 + 250,- 900 + 250,- 900 - + 250,- 900 + 300,- 850 + 250,- 900 + 250,- 900 - + 600,- 550 + 600,- 550 + 300,- 850 + 550,- 600 - + 250,- 900 + 550,- 600 + 550,- 600 + 550,- 600 - + 550,- 600 + 300,- 850 + 250,- 900 + 550,- 600 - + 550,- 600 + 300,- 850 + 550,- 600 + 550,- 600 - + 550,- 600 + 550,- 600 + 550,- 600 + 550,- 600 - + 550,- 600 + 550,- 600 + 550,- 600 + 550,- 600 - + 550,- 600 + 550,- 600 + 600,- 550 + 300,- 900 - + 250,- 900 + 250,- 900 + 550,- 550 + 300,- 850 - + 250,- 900 + 550,- 600 + 550,- 600 + 550,- 600 - + 300,- 850 + 550,- 600 + 550,- 600 + 250,- 900 - + 300,- 850 + 300,- 850 + 600,- 550 + 550,- 600 - + 300,- 850 + 550,- 600 + 550,- 600 + 550 -Sum: 63750 - -Send Bang&Olufsen -- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled -- Now print raw data and try to decode it, which must fail! +Protocol=MagiQuest Address=0xF2 Command=0x187 Raw-Data=0x6BCD00F2 56 bits MSB first +Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, ); rawData[112]: - -1053350 - + 250,-2850 + 250,-2850 + 250,-15250 + 250,-2850 - + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050 - + 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950 - + 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850 - + 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500 - + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + -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 + 350,- 800 + 650,- 550 + 300,- 800 - + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 550 + 300,- 850 - + 300,- 850 + 350,- 800 + 600,- 550 + 600,- 550 - + 300,- 850 + 600,- 550 + 600,- 550 + 650 -Sum: 176100 -Protocol=UNKNOWN Hash=0x4E0DAC41 22 bits (incl. gap and start) received + + 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 -- 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[44]: - -15250 - + 250,-2850 - + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-5950 + 200,-9050 - + 300,-2850 + 200,-9050 + 250,-6000 + 250,-5950 - + 200,-2900 + 200,-9050 + 250,-6000 + 250,-2850 - + 250,-12100 + 250,- 800 + 650,- 500 + 650,- 500 - + 650 -Sum: 118700 +Send next protocols with IrSender.write + +Send JVC +Protocol=JVC Address=0xF2 Command=0x87 Raw-Data=0x87F2 16 bits LSB first +Send with: IrSender.sendJVC(0xF2, 0x87, ); +rawData[36]: + -1085350 + +8400,-4150 + + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 + + 550,-1550 + 550,-1550 + 550,-1550 + 550,-1500 + + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 + + 550,- 500 + 600,- 450 + 600,- 450 + 600,-1500 + + 600 +Sum: 39350 + +Send LG +Protocol=LG Address=0xF2 Command=0xA987 Raw-Data=0xF2A9872 28 bits MSB first +Send with: IrSender.sendLG(0xF2, 0xA987, ); +rawData[60]: + -1039400 + +8900,-4150 + + 550,-1550 + 500,-1550 + 600,-1500 + 550,-1500 + + 550,- 500 + 550,- 500 + 600,-1500 + 550,- 500 + + 550,-1500 + 550,- 500 + 550,-1550 + 550,- 500 + + 550,-1500 + 550,- 500 + 550,- 550 + 550,-1500 + + 550,-1550 + 550,- 500 + 550,- 450 + 600,- 450 + + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 + + 550,- 500 + 550,- 500 + 550,-1500 + 550,- 500 + + 550 +Sum: 57350 Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first -Send with: IrSender.sendBoseWave(0x0, 0x76, ); +Protocol=BoseWave Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first +Send with: IrSender.sendBoseWave(0x0, 0x87, ); rawData[36]: - -1044750 + -1056200 +1050,-1450 - + 550,- 450 + 550,-1400 + 550,-1450 + 550,- 450 - + 500,-1450 + 550,-1450 + 500,-1450 + 550,- 450 - + 550,-1400 + 550,- 450 + 550,- 450 + 550,-1450 - + 500,- 500 + 500,- 450 + 550,- 450 + 550,-1450 - + 500 -Sum: 26750 + + 550,-1400 + 600,-1400 + 550,-1400 + 600,- 400 + + 600,- 400 + 550,- 450 + 550,- 400 + 600,-1400 + + 600,- 400 + 600,- 400 + 550,- 400 + 600,-1400 + + 600,-1400 + 550,-1400 + 600,-1400 + 600,- 400 + + 550 +Sum: 26800 Send FAST -Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first -Send with: IrSender.sendFAST(0x0, 0x76, ); +Protocol=FAST Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first +Send with: IrSender.sendFAST(0x0, 0x87, ); rawData[36]: - -1036750 - +2100,-1050 - + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 - + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 - + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550 - + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550 - + 550 -Sum: 28900 + -1040250 + +2150,-1000 + + 550,-1550 + 550,-1500 + 600,-1550 + 550,- 500 + + 550,- 500 + 600,- 450 + 600,- 450 + 600,-1500 + + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 + + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 + + 600 +Sum: 28950 Force buffer overflow by sending 280 marks and spaces Overflow @@ -688,39 +664,38 @@ ERROR: Unknown protocol address=0xF2 command=0x87 -Send NEC with 8 bit address +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 Send with: IrSender.sendNEC(0xF2, 0x87, ); rawData[68]: -3276750 - +8850,-4500 - + 550,- 500 + 600,-1650 + 600,- 500 + 600,- 550 - + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650 - + 600,-1600 + 600,- 550 + 600,-1650 + 550,-1650 - + 600,- 550 + 550,- 550 + 600,- 550 + 550,- 550 + +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 - + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650 - + 600,- 500 + 550,- 600 + 550,- 550 + 600,-1650 - + 550,-1700 + 550,-1650 + 600,-1650 + 600,- 500 + 600 -Sum: 67600 +Sum: 67850 -Repeat NEC frame for NEC2 -Protocol=NEC2 Address=0xF8 Command=0xED Repeat gap=48600us Raw-Data=0x12ED07F8 32 bits LSB first -!Use the NEC2 protocol for sending! +Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first +Send with: IrSender.sendNEC2(0xF2, 0x87, ); rawData[68]: - -87300 - +8950,-4400 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,- 500 + 650,-1600 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + -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: 67850 +Sum: 67800 Send NEC with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first diff --git a/examples/UnitTest/UnitTest_64bit.log b/examples/UnitTest/UnitTest_64bit.log index e69f1c73b..96c2bffea 100644 --- a/examples/UnitTest/UnitTest_64bit.log +++ b/examples/UnitTest/UnitTest_64bit.log @@ -12,7 +12,7 @@ address=0xFFF1 command=0x76 Send NEC with 8 bit address Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Send with: IrSender.sendNEC(0xF1, 0x76, ); -rawData[68]: +rawData[68]: -1050650 +9050,-4450 + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450 @@ -29,7 +29,7 @@ Sum: 68500 Send NEC with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: +rawData[68]: -1060200 +9050,-4400 + 650,-1600 + 650,- 500 + 650,- 450 + 700,- 450 @@ -46,7 +46,7 @@ Sum: 74050 Send NEC2 with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: +rawData[68]: -1060450 +9050,-4450 + 650,-1600 + 650,- 500 + 650,- 450 + 650,- 500 @@ -63,7 +63,7 @@ Sum: 74150 Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first Send with: IrSender.sendNEC(0x80, 0x45, ); -rawData[68]: +rawData[68]: -1065600 +9200,-4400 + 700,- 450 + 700,- 450 + 700,- 500 + 650,- 500 @@ -80,7 +80,7 @@ Sum: 68800 Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format) Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first Send with: IrSender.sendNEC(0x4, 0x8, ); -rawData[68]: +rawData[68]: -1066550 +9150,-4400 + 650,- 500 + 650,- 450 + 700,-1600 + 650,- 450 @@ -97,7 +97,7 @@ Sum: 68700 Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102) Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first Send with: IrSender.sendOnkyo(0x102, 0x304, ); -rawData[68]: +rawData[68]: -1064800 +9050,-4450 + 650,- 450 + 650,-1600 + 700,- 450 + 650,- 500 @@ -114,7 +114,7 @@ Sum: 56050 Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3) Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first Send with: IrSender.sendNEC(0x102, 0x34, ); -rawData[68]: +rawData[68]: -1066900 +9050,-4400 + 650,- 500 + 650,-1600 + 650,- 500 + 650,- 450 @@ -131,7 +131,7 @@ Sum: 61700 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 with: IrSender.sendPanasonic(0x10B, 0xA0, ); -rawData[100]: +rawData[100]: -1064700 +3550,-1650 + 550,- 350 + 500,-1250 + 500,- 400 + 500,- 350 @@ -153,7 +153,7 @@ 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 with: IrSender.sendPanasonic(0x10B, 0xA0, ); -rawData[100]: +rawData[100]: -1082450 +3550,-1600 + 550,- 350 + 550,-1150 + 550,- 300 + 600,- 300 @@ -174,7 +174,7 @@ Sum: 54200 MSB first Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B02002 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: +rawData[100]: -1076300 +3550,-1600 + 550,- 350 + 550,-1150 + 550,- 300 + 600,- 300 @@ -197,7 +197,7 @@ Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first Send with: uint64_t tRawData[]={0xAFEDCBA987654321, 0x5A}; IrSender.sendPulseDistanceWidthFromArray(38, 9000, 4350, 650, 1600, 650, 500, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); -rawData[148]: +rawData[148]: -1082050 +9000,-4350 + 700,-1600 + 650,- 500 + 700,- 500 + 650,- 500 @@ -224,7 +224,7 @@ 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]: +rawData[106]: -1120100 + 400,- 550 + 700,- 150 + 450,- 500 + 400,- 550 + 400,- 500 @@ -245,7 +245,7 @@ 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, , ); -rawData[66]: +rawData[66]: -1090450 +1100,- 400 + 700,- 150 + 450,- 200 + 450,- 150 + 450,- 200 @@ -261,7 +261,7 @@ 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 Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); -rawData[112]: +rawData[112]: -1070250 + 400,- 800 + 400,- 750 + 450,- 800 + 400,- 750 + 400,- 800 + 400,- 750 + 400,- 800 + 400,- 750 @@ -282,7 +282,7 @@ Sum: 65350 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); -rawData[68]: +rawData[68]: -1086400 +9050,-4400 + 700,-1600 + 650,- 450 + 700,- 450 + 650,- 500 @@ -299,7 +299,7 @@ Sum: 77500 Send Apple Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Send with: IrSender.sendApple(0xF1, 0x76, ); -rawData[68]: +rawData[68]: -1059500 +9050,-4400 + 700,- 500 + 650,-1600 + 700,-1600 + 650,-1600 @@ -316,7 +316,7 @@ Sum: 73000 Send Panasonic Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF102002 48 bits LSB first Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); -rawData[100]: +rawData[100]: -1059200 +3500,-1700 + 500,- 350 + 500,-1250 + 500,- 400 + 500,- 350 @@ -337,7 +337,7 @@ Sum: 65200 Send Kaseikyo with 0x4711 as Vendor ID Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF134711 48 bits LSB first Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); -rawData[100]: +rawData[100]: -1079950 +3550,-1650 + 500,-1250 + 500,- 400 + 500,- 350 + 500,- 400 @@ -358,7 +358,7 @@ Sum: 70500 Send Kaseikyo_Denon variant Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF103254 48 bits LSB first Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, ); -rawData[100]: +rawData[100]: -1080650 +3550,-1650 + 550,- 350 + 500,- 350 + 550,-1200 + 550,- 350 @@ -379,7 +379,7 @@ Sum: 68750 Send Denon Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: +rawData[32]: -1078400 + 350,-1750 + 350,- 700 + 350,- 700 + 350,- 700 + 350,-1750 + 350,- 700 + 300,-1800 + 350,-1750 @@ -390,7 +390,7 @@ Sum: 23450 Send Denon/Sharp variant Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first Send with: IrSender.sendSharp(0x11, 0x76, ); -rawData[32]: +rawData[32]: -1023500 + 350,-1750 + 350,- 700 + 350,- 700 + 350,- 700 + 350,-1750 + 350,- 700 + 350,-1750 + 350,-1750 @@ -401,7 +401,7 @@ Sum: 24500 Send Sony/SIRCS with 7 command and 5 address bits Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: +rawData[26]: -1025750 +2500,- 500 + 700,- 500 +1300,- 650 +1250,- 550 + 700,- 500 @@ -412,7 +412,7 @@ Sum: 21300 Send Sony/SIRCS with 7 command and 8 address bits Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); -rawData[32]: +rawData[32]: -1037600 +2500,- 550 + 650,- 550 +1300,- 500 +1300,- 500 + 700,- 500 @@ -424,7 +424,7 @@ Sum: 26700 Send Sony/SIRCS with 7 command and 13 address bits Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20); -rawData[42]: +rawData[42]: -1041100 +2500,- 500 + 700,- 550 +1300,- 500 +1300,- 500 + 700,- 550 @@ -437,7 +437,7 @@ 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, ); -rawData[68]: +rawData[68]: -1044850 +4550,-4400 + 700,-1600 + 650,- 450 + 700,- 450 + 650,- 500 @@ -454,7 +454,7 @@ Sum: 69600 Send Samsung 16 bit command Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: +rawData[68]: -1061000 +4600,-4400 + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450 @@ -471,7 +471,7 @@ Sum: 69650 Send Samsung48 16 bit command Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0xFFFFFFFF8976FFF1 48 bits LSB first Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); -rawData[100]: +rawData[100]: -1066350 +4550,-4400 + 650,-1650 + 600,- 500 + 700,- 450 + 650,- 500 @@ -492,7 +492,7 @@ Sum: 96750 Send RC5 Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x36, ); -rawData[20]: +rawData[20]: -1079150 +1000,- 800 +1900,-1650 +1900,- 800 +1000,- 800 +1000,-1700 @@ -503,7 +503,7 @@ Sum: 23400 Send RC5X with 7.th MSB of command set Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x76, ); -rawData[20]: +rawData[20]: -1035450 +1900,-1700 +1000,- 800 +1900,- 750 +1000,- 800 +1000,-1700 @@ -514,7 +514,7 @@ Sum: 23400 Send RC6 Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Send with: IrSender.sendRC6(0xF1, 0x76, ); -rawData[36]: +rawData[36]: -1032650 +2750,- 800 + 550,- 800 + 550,- 350 + 550,- 350 + 550,- 800 @@ -524,10 +524,60 @@ rawData[36]: + 550 Sum: 23450 +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 + + 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=0xF2 Command=0x87 Raw-Data=0xF287 16 bits MSB first +Send with: IrSender.sendBang&Olufsen(0xF2, 0x87, ); +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 + +Send MagiQuest +Protocol=MagiQuest Address=0xF2 Command=0x187 Raw-Data=0x6BCD00F2 56 bits MSB first +Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, ); +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 + +Send next protocols with IrSender.write + Send JVC Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first Send with: IrSender.sendJVC(0xF1, 0x76, ); -rawData[36]: +rawData[36]: -1040750 +8500,-4150 + 650,-1500 + 650,- 400 + 650,- 450 + 600,- 450 @@ -537,27 +587,10 @@ rawData[36]: + 650 Sum: 41050 -Send Samsung -Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first -Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: - -1040900 - +4600,-4400 - + 650,-1600 + 700,- 450 + 650,- 500 + 650,- 450 - + 700,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1650 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 700,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 650,-1600 + 650,-1600 + 700,- 450 - + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450 - + 700,- 450 + 650,- 500 + 650,- 450 + 650,-1600 - + 700,-1600 + 650,- 500 + 650,- 450 + 650,-1600 - + 700 -Sum: 69650 - Send LG Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first Send with: IrSender.sendLG(0xF1, 0x9876, ); -rawData[60]: +rawData[60]: -1059650 +9100,-4100 + 650,-1500 + 600,-1500 + 600,-1500 + 600,-1500 @@ -570,45 +603,10 @@ rawData[60]: + 600 Sum: 60450 -Send MagiQuest -Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first -Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -1054600 - + 400,- 750 + 400,- 800 + 400,- 750 + 400,- 750 - + 400,- 800 + 400,- 750 + 400,- 800 + 400,- 750 - + 700,- 500 + 650,- 500 + 400,- 800 + 650,- 500 - + 400,- 750 + 700,- 500 + 700,- 450 + 700,- 500 - + 650,- 500 + 400,- 800 + 400,- 750 + 700,- 500 - + 650,- 500 + 400,- 800 + 650,- 500 + 700,- 450 - + 700,- 500 + 650,- 500 + 700,- 500 + 650,- 500 - + 700,- 450 + 700,- 500 + 700,- 450 + 700,- 500 - + 650,- 500 + 700,- 450 + 700,- 500 + 400,- 750 - + 400,- 800 + 400,- 750 + 700,- 500 + 400,- 800 - + 400,- 750 + 700,- 450 + 700,- 500 + 650,- 500 - + 400,- 800 + 650,- 500 + 700,- 450 + 400,- 800 - + 400,- 750 + 400,- 800 + 650,- 500 + 700,- 500 - + 350,- 800 + 700,- 450 + 700,- 500 + 650 -Sum: 65100 - -Send Bang&Olufsen -Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first -Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, ); -rawData[44]: - -1084600 - + 300,-2850 - + 250,-2900 + 250,-15400 + 300,-2850 + 300,-9100 - + 250,-6050 + 250,-6000 + 250,-6000 + 300,-2850 - + 300,-6000 + 250,-6000 + 300,-9100 + 300,-2850 - + 300,-9100 + 300,-6000 + 250,-6000 + 300,-2850 - + 300,-9100 + 250,-6000 + 300,-2900 + 250,-12250 - + 300 -Sum: 138300 - Send Bosewave with no address and 8 command bits Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Send with: IrSender.sendBoseWave(0x0, 0x76, ); -rawData[36]: +rawData[36]: -1050250 +1100,-1400 + 600,- 400 + 600,-1400 + 600,-1400 + 600,- 400 @@ -621,7 +619,7 @@ Sum: 27150 Send FAST Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Send with: IrSender.sendFAST(0x0, 0x76, ); -rawData[36]: +rawData[36]: -1041350 +2200,-1000 + 650,- 400 + 650,-1500 + 650,-1500 + 600,- 450 @@ -634,7 +632,7 @@ Sum: 29450 Force buffer overflow by sending 280 marks and spaces Overflow Try to increase the "RAW_BUFFER_LENGTH" value of 200 in UnitTest.cpp -rawData[200]: +rawData[200]: -1039850 + 300,- 450 + 300,- 450 + 350,- 450 + 300,- 450 + 350,- 450 @@ -668,27 +666,43 @@ ERROR: Unknown protocol address=0xF2 command=0x87 -Send NEC with 8 bit address +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 Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -3276750 - +9050,-4400 - + 650,- 500 + 650,-1600 + 650,- 500 + 650,- 450 - + 650,-1600 + 700,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 650,- 500 + 650,-1600 + 700,-1550 - + 650,- 500 + 650,- 500 + 600,- 500 + 700,- 450 - + 650,-1600 + 650,-1600 + 700,-1600 + 650,- 450 - + 700,- 450 + 650,- 500 + 650,- 450 + 700,-1550 - + 700,- 450 + 650,- 500 + 650,- 500 + 650,-1600 - + 650,-1650 + 650,-1600 + 650,-1600 + 650,- 500 - + 650 -Sum: 68450 + +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 + + 600 +Sum: 67850 + +Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first +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 Send NEC with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -1060000 +9100,-4400 + 650,- 450 + 700,-1600 + 650,- 450 + 700,- 450 @@ -705,7 +719,7 @@ Sum: 68450 Send NEC2 with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -1060100 +9050,-4400 + 700,- 450 + 650,-1600 + 650,- 500 + 650,- 450 @@ -722,7 +736,7 @@ Sum: 68450 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Send with: IrSender.sendOnkyo(0xF2, 0x8887, ); -rawData[68]: +rawData[68]: -1060700 +9100,-4400 + 650,- 450 + 700,-1600 + 650,- 450 + 700,- 450 @@ -739,7 +753,7 @@ Sum: 62800 Send Apple Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Send with: IrSender.sendApple(0xF2, 0x87, ); -rawData[68]: +rawData[68]: -1059150 +9050,-4400 + 650,- 500 + 650,-1600 + 650,-1600 + 700,-1600 @@ -756,7 +770,7 @@ Sum: 71800 Send Panasonic Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F202002 48 bits LSB first Send with: IrSender.sendPanasonic(0xF2, 0x87, ); -rawData[100]: +rawData[100]: -1069050 +3550,-1650 + 500,- 400 + 500,-1250 + 500,- 350 + 500,- 400 @@ -777,7 +791,7 @@ Sum: 60000 Send Kaseikyo with 0x4711 as Vendor ID Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F234711 48 bits LSB first Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711); -rawData[100]: +rawData[100]: -1079750 +3550,-1650 + 550,-1200 + 550,- 350 + 500,- 350 + 550,- 350 diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 5f9ed1bb2..06d71bcad 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -118,9 +118,14 @@ struct IRData { uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above - // These 2 variables allow to call resume() directly after decode, if no dump is required. Since 4.3.0. - IRRawlenType rawlen; ///< counter of entries in rawbuf - uint16_t initialGap; ///< rawbuf[0] contains the initial gap of the last frame. + /* + * These 2 variables allow to call resume() directly after decode. + * After resume(), decodedIRData.rawDataPtr->rawbuf[0] 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 initialGap; ///< contains the initial gap (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. }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index b6a5f4734..2e444c455 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -486,7 +486,12 @@ void IRrecv::initDecodedIRData() { } - //These 2 variables allow to call resume() directly after decode, if no dump is required. since 4.3.0. + /* + * These 2 variables allow to call resume() directly after decode. + * After resume(), decodedIRData.rawDataPtr->rawbuf[0] and decodedIRData.rawDataPtr->rawlen are + * the first variables, which are overwritten by the next received frame. + * since 4.3.0. + */ decodedIRData.initialGap = decodedIRData.rawDataPtr->rawbuf[0]; decodedIRData.rawlen = decodedIRData.rawDataPtr->rawlen; @@ -1332,22 +1337,16 @@ uint32_t IRrecv::getTotalDurationOfRawData() { /** * 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. * Ends with println(). * !!!Attention: The result differs on a 8 bit or 32 bit platform!!! * * @param aSerial The Print object on which to write, for Arduino you can use &Serial. */ void IRrecv::printIRSendUsage(Print *aSerial) { - if (decodedIRData.flags & IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT) { - /* - * Here we have a repeat of type NEC2 or SamsungLG. -> Inform the user to use this and not the initial protocol for sending. - */ - Serial.print(F("!Use the ")); - Serial.print(getProtocolString()); - Serial.println(F(" protocol for sending!")); - } else { - if (decodedIRData.protocol != UNKNOWN - && (decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00) { + if (decodedIRData.protocol != UNKNOWN + && ((decodedIRData.flags & (IRDATA_FLAGS_IS_AUTO_REPEAT | IRDATA_FLAGS_IS_REPEAT)) == 0x00 + || (decodedIRData.flags & IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT))) { #if defined(DECODE_DISTANCE_WIDTH) uint_fast8_t tNumberOfArrayData = 0; if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) { @@ -1383,7 +1382,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(F("IrSender.send")); #else - aSerial->print(F("Send with: IrSender.send")); + aSerial->print(F("Send with: IrSender.send")); #endif #if defined(DECODE_DISTANCE_WIDTH) @@ -1458,9 +1457,8 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(decodedIRData.extra, HEX); } #endif - aSerial->print(F(");")); - aSerial->println(); - } + aSerial->print(F(");")); + aSerial->println(); } } diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 59297ba8d..cecdfb0d7 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -68,11 +68,16 @@ * 100 is sufficient for most standard protocols, but air conditioners often send a longer protocol data stream */ #if !defined(RAW_BUFFER_LENGTH) -# if defined(DECODE_MAGIQUEST) +# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +// for RAMsize <= 2k +# if defined(DECODE_MAGIQUEST) #define RAW_BUFFER_LENGTH 112 // MagiQuest requires 112 bytes. -# else +# else #define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit. -//#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. +# endif +# else +// For undefined or bigger RAMsize +#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. # endif #endif #if RAW_BUFFER_LENGTH % 2 == 1 @@ -383,19 +388,18 @@ void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please us #define TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING 25 // Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. #endif -/** Lower tolerance for comparison of measured data */ -//#define LTOL (1.0 - (TOLERANCE/100.)) -#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) -/** Upper tolerance for comparison of measured data */ -//#define UTOL (1.0 + (TOLERANCE/100.)) -#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) - //#define TICKS_LOW(us) ((int)(((us)*LTOL/MICROS_PER_TICK))) //#define TICKS_HIGH(us) ((int)(((us)*UTOL/MICROS_PER_TICK + 1))) #if MICROS_PER_TICK == 50 && TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING == 25 // Defaults #define TICKS_LOW(us) ((us)/67 ) // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100) #define TICKS_HIGH(us) (((us)/40) + 1) // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1 #else +/** Lower tolerance for comparison of measured data */ +//#define LTOL (1.0 - (TOLERANCE/100.)) +#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) +/** Upper tolerance for comparison of measured data */ +//#define UTOL (1.0 + (TOLERANCE/100.)) +#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) #define TICKS_LOW(us) ((uint16_t ) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) )) #define TICKS_HIGH(us) ((uint16_t ) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1)) #endif diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index d5eb42ace..19de58ce6 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1435,7 +1435,7 @@ void timerConfigForReceive() { **********************************************************/ #elif defined(ESP32) # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) -#error This library does not work with ESP32 core 3.x. You are kindly invited to port and document the code to 3.x, to fix this problem! +#error This library does not work with ESP32 core 3.x. Please use ESP 2.0.17 core. You are kindly invited to port and document the code to 3.x, to fix this problem! # endif // Variables specific to the ESP32. From 8f23b6bfa81b1ab78183005aea4be52d75bf92d9 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 16 Jun 2024 19:39:10 +0200 Subject: [PATCH 049/133] closes #1240 --- src/LongUnion.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LongUnion.h b/src/LongUnion.h index 3559ac214..8f90f6135 100644 --- a/src/LongUnion.h +++ b/src/LongUnion.h @@ -87,7 +87,7 @@ union LongUnion { struct { WordUnion LowWord; WordUnion HighWord; - } WordUnion; + } TwoWordUnions; uint8_t UBytes[4]; // seems to have the same code size as using struct UByte int8_t Bytes[4]; // Bytes[0] is LowByte uint16_t UWords[2]; @@ -122,7 +122,7 @@ union LongLongUnion { WordUnion MidLowWord; WordUnion MidHighWord; WordUnion HighWord; - } WordUnion; + } FourWordUnions; struct { uint32_t LowLong; uint32_t HighLong; @@ -134,7 +134,7 @@ union LongLongUnion { struct { LongUnion LowLong; LongUnion HighLong; - } LongUnion; + } TwoLongUnions; uint8_t UBytes[8]; // seems to have the same code size as using struct UByte int8_t Bytes[8]; uint16_t UWords[4]; From fd5397d8251e1941a79bd7c98d7bb6a5d8200cb3 Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 21 Jun 2024 17:29:19 +0200 Subject: [PATCH 050/133] Bumped version to 4.4. Improved sensitivity of PULSE_DISTANCE + PULSE_WIDTH protocols. New functions decodePulseDistanceWidthData() with 6 parameters and decodePulseDistanceWidthDataStrict() with 7 parameter. --- README.md | 95 +- changelog.md | 5 +- examples/AllProtocolsOnLCD/ADCUtils.hpp | 3 + examples/IRremoteInfo/IRremoteInfo.ino | 2 +- .../ReceiveAndSendHob2Hood.ino | 2 +- examples/SendDemo/SendDemo.ino | 22 +- examples/SendRawDemo/SendRawDemo.ino | 52 +- examples/UnitTest/UnitTest.ino | 64 +- examples/UnitTest/UnitTest.log | 1109 +++++++++-------- library.json | 2 +- library.properties | 2 +- src/IRProtocol.h | 13 +- src/IRReceive.hpp | 224 +++- src/IRSend.hpp | 20 +- src/IRVersion.h | 8 +- src/IRremoteInt.h | 24 +- src/ir_Denon.hpp | 4 +- src/ir_DistanceWidthProtocol.hpp | 105 +- src/ir_JVC.hpp | 2 +- src/ir_LG.hpp | 2 +- src/ir_MagiQuest.hpp | 7 +- src/ir_NEC.hpp | 2 +- src/ir_Samsung.hpp | 3 +- src/ir_Sony.hpp | 2 +- src/private/IRTimer.hpp | 14 +- 25 files changed, 1059 insertions(+), 729 deletions(-) diff --git a/README.md b/README.md index cf30f46bd..4324754cb 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) +- [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) @@ -93,7 +94,9 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr ` JVC `     ` LG `     ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` -` Universal Pulse Distance `     ` Universal Pulse Width `     ` Hash `     ` Pronto ` +` Universal Pulse Distance `     ` Universal Pulse Width `     ` Universal Pulse Distance Width` + +` Hash `     ` Pronto ` ` BoseWave `     ` Bang & Olufsen `     ` Lego `     ` FAST `     ` Whynter `     ` MagiQuest ` @@ -113,13 +116,13 @@ Protocols can be switched off and on by defining macros before the line `#includ ## New features with version 4.x - **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead. -- New universal **Pulse Distance / Pulse Width decoder** added, which covers many previous unknown protocols. +- 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. - **Callback** after receiving a command - It calls your code as soon as a message was received. - Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. - New FAST protocol. -- Automatic printout of the **corresponding send function** with printIRSendUsage(). +- Automatic printout of the **corresponding send function** with `printIRSendUsage()`. #### Converting your 3.x program to the 4.x version - You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder). @@ -255,7 +258,7 @@ If this doesn't fit your case, be assured that 4.x is at least trying to be back ` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` - The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. -- No decoding to a more meaningfull (constant) 8/16 bit address and 8 bit command. +- No decoding to a more meaningful (constant) 8/16 bit address and 8 bit command.
@@ -297,11 +300,55 @@ The following macros will definitely be overridden with default values otherwise
+# 3 ways to specify an IR code +There are 3 different ways of specifying a particular IR code. + +## 1. Timing +The timing of each mark/pulse and space/distance_between_pulses is specified in a list or array. +This enables specifying **all IR codes**, but requires a lot of memory and is **not readable at all**. +One formal definition of such a timing array, including **specification of frequency and repeats** is the [**Pronto** format](http://www.harctoolbox.org/Glossary.html#ProntoSemantics).
+Memory can be saved by using a lower time resolution. +For IRremote you can use a 50 µs resolution which halves the memory requirement by using byte values instead of int16 values. +For receiving purposes you can use the **hash of the timing** provided by the `decodeHash()` decoder. + +## 2. Encoding schemes +There are 3 main encoding schemes which encodes a binary bitstream / hex value: +1. `PULSE_DISTANCE`. The distance between pulses determines the bit value. This requires always a stop bit! +Examples are NEC and KASEIKYO protocols. The pulse width is constant for most protocols. +2. `PULSE_WIDTH`. The width of a pulse determines the bit value, pulse distance is constant. This requires no stop bit! +The only known example is the SONY protocol. +3. [Phase / Manchester encoding](https://en.wikipedia.org/wiki/Manchester_code). +The time of the pulse/pause transition (phase) relative to the clock determines the bit value. Examples are RC5 and RC6 protocols. + +Phase encoding has a **constant bit length**, `PULSE_DISTANCE` with constant pulse width and `PULSE_WIDTH` have **no constant bit length**! + +A well known example for `PULSE_DISTANCE` with non constant pulse width encoding is the **RS232 serial encoding**. +Here the non constant pulse width is used to enable a **constant bit length**. + +Most IR signals have a **special header** to help in setting the automatic gain of the receiver circuit. +This header is not part of the encoding, but is often significant for a special protocol and therefore must be reproducible. + +Be aware that there are codes using a `PULSE_DISTANCE` encoding where more than a binary 0/1 is put into a pulse/pause combination. +This requires more than 2 different pulse or pause length combinations. +The [HobToHood protocol](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino) uses such an encoding. + +Using encoding schemes reduces the specification of an IR code to a bitstream / hex value, which is LSB by default and pulse / pause timings of header, 0, and 1. +The hex value is **quite readable**. +These schemes can not put any semantics like address, command or checksum on this bitstream. + +## 3. Protocols +There are a few common protocols that are implemented directly in IRremote. +They specify the frequency, the timings of header, 0, and 1 as well as other values like checksum, repeat distance, repeat coding, bit toggling etc. +The semantics of the hex value is also specified, allowing the usage of only 2 parameters **address** and **command** to specify an IR code. +This saves memory and is **highly readable**. +Often the address is also constant, which further reduces memory requirements. + + # IRReceiver pinouts ![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) # Receiving IR codes -In your program you check for a **completly received IR frame** with:
+In your program you check for a **completely received IR frame** with:
`if (IrReceiver.decode()) {}`
This also decodes the received data.
After successful decoding, the IR data is contained in the IRData structure, available as `IrReceiver.decodedIRData`. @@ -415,13 +462,15 @@ Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `s 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. -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)`.
+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. ## Send pin -Any pin can be choosen as send pin, because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
-On **ESP32** ledc channel 0 is used for gereating 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). +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.
+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). ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html @@ -518,15 +567,17 @@ The FAST protocol can be received by IRremote and TinyIRReceiver. # FAQ and hints ## Receiving stops after analogWrite() or tone() or after running a motor. -The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). On some boards where a software timer is available, the software timer is used.
+The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). +On some boards where a software timer is available, the software timer is used.
Be aware that the hardware timer used for receiving should not be used for `analogWrite()`.
Especially **motor** control often uses the `analogWrite()` function and will therefore stop the receiving if used on the pins indicated [here](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage).
-On the Uno and other AVR boards the receiver timer ist the same as the tone timer. Thus receiving will stop after a `tone()` command. See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/b962db8f4e47408df01474a57f313f5a6bbe39a1/examples/ReceiveDemo/ReceiveDemo.ino#L257) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`. +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()`. ## 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. +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. Best is to dump the timing then, to see which reason holds. ## Problems with Neopixels, FastLed etc. @@ -587,16 +638,16 @@ If you get something like this: PULSE_DISTANCE: HeaderMarkMicros=8900 HeaderSpaceMicros=4450 MarkMicros=550 OneSpaceMicros=1700 ZeroSpaceMicros=600 NumberOfBits=56 0x43D8613C 0x3BC3BC ``` then you have a code consisting of **56 bits**, which is probably from an air conditioner remote.
-You can send it with sendPulseDistance(). +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 PulseDistance or PulseWidth decoders just decode a timing stream to a bit stream**. -They can not put any semantics like address, command or checksum on this bitstream, since it is no known protocol. +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 this does not suit you for further research, you can change it [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_DistanceProtocol.hpp#L78). +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.** @@ -733,7 +784,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| | `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 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. | -| `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. | +| `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. | | `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. | | `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | @@ -752,7 +803,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | | `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. | -| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` | 25 | Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. | +| `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT` | 25 | Relative tolerance for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. | | `DEBUG` | disabled | Enables lots of lovely debug output. | | `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. | @@ -931,7 +982,7 @@ The IR signal is sampled at a **50 µs interval**. For a constant 525 &micr And believe me, if you send a 525 µs signal, your receiver will output something between around 400 and 700 µs!
Therefore **we decode by default with a +/- 25% margin** using the formulas [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremoteInt.h#L376-L399).
E.g. for the NEC protocol with its 560 µs unit length, we have TICKS_LOW = 8.358 and TICKS_HIGH = 15.0. This means, we accept any value between 8 ticks / 400 µs and 15 ticks / 750 µs (inclusive) as a mark or as a zero space. For a one space we have TICKS_LOW = 25.07 and TICKS_HIGH = 45.0.
-And since the receivers generated marks are longer or shorter than the spaces, +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**. diff --git a/changelog.md b/changelog.md index c8d360a81..2891903f8 100644 --- a/changelog.md +++ b/changelog.md @@ -2,10 +2,13 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master -# 4.3.3 +# 4.4.0 - sendNEC() and sendNEC2() now accepts 16 bit command to better map to NECext protocol found in IRDB databases. - ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. +- Improved sensitivity and decoding of PULSE_DISTANCE + PULSE_WIDTH protocols. +- Changed TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING to TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT. - Improved examples AllProtocolsOnLCD, UnitTest and SimpleReceiver. +- New functions decodePulseDistanceWidthData() with 6 parameters and decodePulseDistanceWidthDataStrict() with 7 parameters. # 4.3.2 - Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index b5e04f5b3..73030b475 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -762,6 +762,9 @@ float getCPUTemperatureSimple(void) { #if defined(__AVR_ATmega328PB__) tTemperatureRaw -= 245; return (float)tTemperatureRaw; +#elif defined(__AVR_ATtiny85__) + tTemperatureRaw -= 273; // 273 and 1.1666 are values from the datasheet + return (float)tTemperatureRaw / 1.1666; #else tTemperatureRaw -= 317; return (float) tTemperatureRaw / 1.22; diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino index 34c207ad0..31d037668 100644 --- a/examples/IRremoteInfo/IRremoteInfo.ino +++ b/examples/IRremoteInfo/IRremoteInfo.ino @@ -197,7 +197,7 @@ void dumpPulseParams() { ; Serial.println(F(" uSecs")); Serial.print(F("Measurement tolerance: ")); - Serial.print(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING); + Serial.print(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT); Serial.println(F("%")); } diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index 41e5703be..159dad611 100644 --- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -93,7 +93,7 @@ void setup() { } /* - * Send Hob2Hood protocol + * Receive and send Hob2Hood protocol */ void loop() { static long sLastMillisOfSend = 0; diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 278b88a0d..c644f3e4c 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -199,9 +199,9 @@ void loop() { delay(DELAY_AFTER_SEND); /* - * Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first + * Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first */ - Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance")); + Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance")); Serial.println(F(" LSB first")); Serial.flush(); #if __INT_WIDTH__ < 32 @@ -226,7 +226,7 @@ void loop() { #endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); + Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first @@ -240,7 +240,7 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); + Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); Serial.flush(); // Real PulseDistanceWidth (constant bit length) does not require a stop bit #if __INT_WIDTH__ < 32 @@ -252,7 +252,19 @@ void loop() { #endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first")); + Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first")); + 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.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); + + Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first")); 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); diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 9af3bc1f7..8e1847517 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -3,8 +3,7 @@ * * This example shows how to send a RAW signal using the IRremote library. * The example signal is actually a 32 bit NEC signal. - * Remote Control button: LGTV Power On/Off. - * Hex Value: 0x20DF10EF, 32 bits + * Protocol=NEC Address=0x4 Command=0x18 Raw-Data=0xE718FB04 32 bits LSB first * * If it is a supported protocol, it is more efficient to use the protocol send function * (here sendNEC) to send the signal. @@ -14,7 +13,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2022 Armin Joachimsmeyer + * Copyright (c) 2020-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -68,9 +67,9 @@ void setup() { } /* - * NEC address=0xFB0C, command=0x18 + * NEC address=0x04 (0xFB04), command=0x18 (0xE718) * - * This is data in byte format. + * This is the raw data array in byte format. * The uint8_t/byte elements contain the number of ticks in 50 us. * The uint16_t format contains the (number of ticks * 50) if generated by IRremote, * so the uint16_t format has exact the same resolution but requires double space. @@ -78,49 +77,52 @@ void setup() { * e.g. use 560 (instead of 11 * 50) for NEC or use 432 for Panasonic. But in this cases, * you better use the timing generation functions e.g. sendNEC() directly. */ -const uint8_t rawDataP[] -#if defined(__AVR__) -PROGMEM -#endif -= { 180, 90 /*Start bit*/, 11, 11, 11, 11, 11, 34, 11, 34/*0011 0xC of 16 bit address LSB first*/, 11, 11, 11, 11, 11, 11, 11, +const uint8_t rawDataP[] PROGMEM += { 180, 90 /*Start bit*/, 11, 11, 11, 11, 11, 34, 11, 11/*0010 0x4 of 8 bit address LSB first*/, 11, 11, 11, 11, 11, 11, 11, 11/*0000*/, 11, 34, 11, 34, 11, 11, 11, 34/*1101 0xB*/, 11, 34, 11, 34, 11, 34, 11, 34/*1111*/, 11, 11, 11, 11, 11, 11, 11, 34/*0001 0x08 of command LSB first*/, 11, 34, 11, 11, 11, 11, 11, 11/*1000 0x01*/, 11, 34, 11, 34, 11, 34, 11, 11/*1110 Inverted 8 of command*/, 11, 11, 11, 34, 11, 34, 11, 34/*0111 inverted 1 of command*/, 11 /*stop bit*/}; +/* + * The same frame as above. Values are NOT multiple of 50, but are taken from the NEC timing definitions + */ +const uint16_t rawData[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, + 560/*0010 0x4 of 8 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, + 560, 1690/*1101 0xB - inverted 0x04*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111 - inverted 0*/, 560, 560, 560, 560, + 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 1690, 560, 560, 560, 560, 560, 560/*1000 0x01*/, 560, 1690, 560, + 1690, 560, 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 560, 560, 1690, 560, 1690, 560, + 1690/*1111 inverted 0 of command*/, 560 /*stop bit*/}; // Using exact NEC timing + void loop() { -#if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) +#if FLASHEND > 0x1FFF // For more than 8k flash => not for ATtiny85 etc. /* * Send hand crafted data from RAM - * The values are NOT multiple of 50, but are taken from the NEC timing definitions */ - Serial.println(F("Send NEC 16 bit address=0xFB04 and command 0x08 with exact timing (16 bit array format)")); + Serial.println(F("Send NEC 8 bit address=0x04 (0xFB04) and command 0x18 (0xE718) with exact timing (16 bit array format)")); Serial.flush(); - - const uint16_t rawData[] = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, - 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, - 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, - 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000 0x00*/, 560, 1690, 560, 1690, 560, - 1690, 560, 560/*1110 Inverted 8 of command*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111 inverted 0 of command*/, - 560 /*stop bit*/}; // Using exact NEC timing IrSender.sendRaw(rawData, sizeof(rawData) / sizeof(rawData[0]), NEC_KHZ); // Note the approach used to automatically calculate the size of the array. - delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal + delay(1000); // delay must be greater than 8 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal + #endif /* * Send byte data direct from FLASH * Note the approach used to automatically calculate the size of the array. */ - Serial.println(F("Send NEC 16 bit address 0xFB0C and data 0x18 with (50 us) tick resolution timing (8 bit array format) ")); + Serial.println(F("Send NEC 8 bit address 0x04 and command 0x18 with (50 us) tick resolution timing (8 bit array format) ")); Serial.flush(); IrSender.sendRaw_P(rawDataP, sizeof(rawDataP) / sizeof(rawDataP[0]), NEC_KHZ); - delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal + delay(1000); // delay must be greater than 8 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal - Serial.println(F("Send NEC 16 bit address 0x0102, 8 bit data 0x34 with generated timing")); + /* + * Send the same frame using NEC encoder + */ + Serial.println(F("Send NEC 16 bit address 0x04, 8 bit command 0x18 with NEC encoder")); Serial.flush(); - IrSender.sendNEC(0x0102, 0x34, 0); + IrSender.sendNEC(0x04, 0x18, 0); delay(3000); } diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 8bdcb44b1..a499fa1b1 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -469,10 +469,10 @@ void loop() { # endif # if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) - Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants")); + Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); Serial.flush(); # if __INT_WIDTH__ < 32 - IRRawDataType tRawData[] = { 0xB02002, 0xA010, 0x0 }; // LSB of tRawData[0] is sent first + 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 checkReceive(0x0B, 0x10); # else @@ -482,9 +482,9 @@ void loop() { delay(DELAY_AFTER_SEND); /* - * Send 2 Panasonic 48 bit codes as generic Pulse Distance data, once with LSB and once with MSB first + * Send 2 Panasonic 48 bit codes as Pulse Distance data, once with LSB and once with MSB first */ - Serial.println(F("Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance")); + Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance")); Serial.println(F("-LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 @@ -516,7 +516,7 @@ void loop() { # if defined(DECODE_DISTANCE_WIDTH) # if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) - Serial.println(F("Send generic 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first")); + Serial.println(F("Send 52 bit PulseDistance 0x43D8613C and 0x3BC3B MSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 tRawData[0] = 0x43D8613C; // MSB of tRawData[0] is sent first @@ -530,7 +530,7 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first")); + Serial.println(F("Send 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first")); Serial.flush(); // Real PulseDistanceWidth (constant bit length) does not require a stop bit # if __INT_WIDTH__ < 32 @@ -541,7 +541,7 @@ void loop() { checkReceivedRawData(0x123456789ABC); # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 32 bit PulseWidth 0x43D8613C MSB first")); + Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first")); 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 +549,7 @@ void loop() { delay(DELAY_AFTER_SEND); # else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) - Serial.println(F("Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); + Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first @@ -565,35 +565,63 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); + Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); Serial.flush(); - // Real PulseDistanceWidth (constant bit length) does not require a stop bit + // Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission # if __INT_WIDTH__ < 32 tRawData[1] = 0xDCBA9; - IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); + IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 300, 600, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); # else - IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); + IrSender.sendPulseDistanceWidth(38, 300, 600, 300, 600, 600, 300, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0xDCBA987654321); # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send generic 32 bit PulseWidth 0x87654321 LSB first")); + Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data")); + Serial.flush(); +# if __INT_WIDTH__ < 32 + tRawData[2] = ~tRawData[0]; + tRawData[3] = ~tRawData[1]; + IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); + checkReceivedArray(tRawData, 2); +# else + IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); + checkReceivedRawData(0xDCBA987654321); +# endif + delay(DELAY_AFTER_SEND); + + Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first")); + 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.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); + checkReceive(sAddress & 0x1F, sCommand & 0x7F); + delay(DELAY_AFTER_SEND); + + Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first")); Serial.flush(); - // Real PulseDistanceWidth (constant bit length) does not require a stop bit IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0x87654321); delay(DELAY_AFTER_SEND); + # 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 generic 55 bit PulseDistanceWidth MSB first")); + Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 tRawData[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left - tRawData[1] = 0x017619; // We send only 23 instead of 24 bite here! 19 is the checksum - IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData[0], 55, PROTOCOL_IS_MSB_FIRST, 0, 0); + 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, + 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); @@ -664,7 +692,7 @@ void loop() { #if defined(DECODE_SONY) Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits")); Serial.flush(); - IrSender.sendSony(sAddress & 0x1F, sCommand, 0); + IrSender.sendSony(sAddress & 0x1F, sCommand, 0); // SIRCS_12_PROTOCOL is default checkReceive(sAddress & 0x1F, sCommand & 0x7F); delay(DELAY_AFTER_SEND); diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index d9e61435b..e96beb259 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -1,6 +1,6 @@ -START ../src/UnitTest.cpp from Feb 22 2023 -Using library version 4.1.0 -Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Bosewave , MagiQuest, Universal Pulse Distance Width, Hash at pin 2 +START ../src/UnitTest.cpp from 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 Use ReceiveCompleteCallback Receive buffer length is 200 Send IR signals at pin 3 @@ -15,326 +15,304 @@ Send NEC with 8 bit address Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Send with: IrSender.sendNEC(0xF1, 0x76, ); rawData[68]: - -1044300 - +8950,-4400 - + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650 - + 550,- 550 + 600,-1650 + 600,-1650 + 550,-1650 - + 600,- 550 + 550,- 550 + 600,- 550 + 550,- 600 - + 550,- 550 + 550,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 550,- 600 + 550,- 550 + 600,-1800 - + 450,- 500 + 600,- 550 + 550,- 550 + 600,-1650 - + 550 -Sum: 67650 + -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 + + 600 +Sum: 67800 Send NEC with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); rawData[68]: - -1055100 - +8850,-4450 - + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650 - + 550,-1650 + 600,-1650 + 550,-1700 + 550,-1650 - + 550,- 600 + 550,-1650 + 600,-1650 + 600,- 550 - + 550,-1650 + 600,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,- 550 + 550,- 550 + 600,-1650 - + 600,- 500 + 550,- 600 + 600,- 500 + 600,-1650 - + 550 -Sum: 73150 + -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 Send NEC2 with 16 bit address Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Send with: IrSender.sendNEC(0xFFF1, 0x76, ); rawData[68]: - -1055500 + -1059050 +8950,-4400 - + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 450 - + 650,-1600 + 650,- 500 + 600,- 500 + 600,-1650 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650 -Sum: 73400 - -Send NEC Pronto data with 8 bit address 0x80 and command 0x45 and no repeats -Protocol=NEC Address=0x80 Command=0x45 Raw-Data=0xBA457F80 32 bits LSB first -Send with: IrSender.sendNEC(0x80, 0x45, ); -rawData[68]: - -1064450 - +9050,-4450 - + 550,- 550 + 600,- 550 + 600,- 600 + 550,- 600 - + 600,- 550 + 600,- 550 + 600,- 550 + 600,-1600 - + 650,-1600 + 600,-1600 + 600,-1650 + 550,-1600 - + 600,-1600 + 600,-1600 + 600,-1600 + 650,- 500 - + 650,-1550 + 600,- 550 + 600,-1600 + 600,- 550 - + 600,- 550 + 600,- 550 + 600,-1600 + 600,- 550 - + 650,- 500 + 650,-1550 + 600,- 550 + 600,-1600 - + 600,-1600 + 600,-1650 + 600,- 550 + 600,-1650 - + 550 -Sum: 67800 - -Send NEC sendRaw data with 8 bit address=0xFB04 and command 0x08 and exact timing (16 bit array format) -Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0xF708FB04 32 bits LSB first -Send with: IrSender.sendNEC(0x4, 0x8, ); -rawData[68]: - -1061400 - +9000,-4400 - + 600,- 500 + 650,- 500 + 600,-1650 + 600,- 500 - + 650,- 500 + 600,- 550 + 600,- 500 + 600,- 550 - + 600,-1650 + 600,-1650 + 600,- 500 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1650 - + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650 - + 600,- 500 + 600,- 550 + 600,- 500 + 600,- 550 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1650 + + 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 + 600 -Sum: 67900 - -Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102) -Protocol=Onkyo Address=0x102 Command=0x304 Raw-Data=0x3040102 32 bits LSB first -Send with: IrSender.sendOnkyo(0x102, 0x304, ); -rawData[68]: - -1059700 - +8900,-4400 - + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 500 - + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 550 - + 550,- 550 + 600,- 500 + 600,-1650 + 600,- 500 - + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 500 - + 600,-1650 + 600,-1600 + 600,- 550 + 600,- 500 - + 650,- 500 + 600,- 550 + 550,- 550 + 600,- 500 - + 650 -Sum: 55450 +Sum: 73300 -Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3) -Protocol=NEC Address=0x102 Command=0x34 Raw-Data=0xCB340102 32 bits LSB first -Send with: IrSender.sendNEC(0x102, 0x34, ); -rawData[68]: - -1061500 - +8950,-4400 - + 600,- 500 + 550,-1700 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 550,- 550 + 650,- 500 - + 600,-1650 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500 - + 600,- 550 + 600,- 500 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,-1650 + 600,- 500 + 600,- 550 - + 600,-1600 + 550,-1700 + 600,- 550 + 600,-1600 - + 600,- 550 + 600,- 500 + 650,-1600 + 600,-1650 - + 550 -Sum: 61000 - -Send Panasonic 0xB, 0x10 as 48 bit generic PulseDistance using ProtocolConstants +Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1059500 + -1062700 +3450,-1700 - + 450,- 450 + 450,-1250 + 450,- 400 + 450,- 450 - + 450,- 400 + 450,- 400 + 450,- 450 + 400,- 450 - + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400 - + 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450 - + 400,- 450 + 450,- 400 + 450,- 450 + 400,- 450 - + 450,-1300 + 400,-1300 + 450,- 400 + 450,-1300 + + 450,- 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 - + 450,- 450 + 400,- 450 + 450,- 400 + 450,- 450 - + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400 - + 450,-1300 + 400,- 450 + 450,- 450 + 400,- 450 - + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400 - + 450,- 450 + 400,-1300 + 450,- 400 + 450,-1300 + + 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: 54100 +Sum: 54150 -Send Panasonic 0xB, 0x10 as generic 48 bit PulseDistance -- LSB first +Send Panasonic 0xB, 0x10 as 48 bit PulseDistance +-LSB first Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1076450 - +3450,-1700 - + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 - + 450,- 400 + 400,- 450 + 400,- 450 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,-1250 + 450,-1250 + 450,- 400 + 450,-1250 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 350 - + 500,- 400 + 400,- 450 + 450,- 350 + 500,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,-1250 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,-1200 + 500,- 400 + 450,-1300 - + 400 + -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 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,- 400 + 450,-1200 + 500,- 350 + 500,-1200 + + 500 Sum: 53200 -- MSB first +-MSB first Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1070700 - +3400,-1700 - + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,-1250 + 450,- 400 + 450,- 400 - + 400,- 450 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,-1250 + 400,-1300 + 450,- 400 + 450,-1300 - + 400,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 - + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 550 - + 250,-1300 + 450,- 450 + 400,- 400 + 450,- 400 - + 450,- 400 + 400,- 450 + 400,- 450 + 450,- 400 - + 450,- 400 + 450,-1250 + 450,- 400 + 450,-1250 - + 450 -Sum: 53150 + -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 -Send generic 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first +Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A}; - IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 550, 1650, 550, 600, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); rawData[148]: - -1076300 + -1079150 +8850,-4400 - + 600,-1650 + 550,- 600 + 550,- 600 + 550,- 600 - + 550,- 600 + 550,-1650 + 550,- 650 + 550,- 600 - + 550,-1700 + 550,-1650 + 600,- 600 + 550,- 600 - + 550,- 600 + 500,- 650 + 550,-1650 + 600,- 600 - + 550,-1650 + 600,- 600 + 550,-1650 + 550,- 650 - + 550,- 600 + 550,-1650 + 550,-1700 + 550,- 600 - + 550,-1700 + 550,-1700 + 550,-1650 + 550,- 650 - + 550,- 600 + 550,- 600 + 550,- 600 + 550,-1700 - + 550,-1700 + 550,- 600 + 550,- 600 + 550,-1650 - + 500,- 700 + 550,-1650 + 600,- 600 + 550,-1650 - + 600,-1650 + 600,-1650 + 550,- 650 + 550,-1650 - + 550,- 600 + 550,- 600 + 550,-1700 + 550,-1700 - + 550,-1650 + 600,- 600 + 550,-1650 + 600,-1650 - + 600,- 600 + 550,-1650 + 550,-1700 + 550,-1700 - + 550,-1700 + 550,-1700 + 550,-1700 + 550,-1650 - + 550,- 650 + 550,-1650 + 550,- 650 + 550,-1700 - + 550,- 600 + 550,-1650 + 600,- 550 + 600,-1650 - + 550,-1700 + 550,- 600 + 550,-1700 + 550,- 600 - + 550 -Sum: 138200 + + 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 + + 600 +Sum: 138350 -Send generic 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first -Protocol=PulseWidth Raw-Data=0xDCBA9 52 bits LSB first +Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first +Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[106]: - -1115100 - + 350,- 600 - + 650,- 250 + 350,- 550 + 350,- 550 + 300,- 600 + 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 - + 600,- 300 + 600,- 300 + 350,- 550 + 350,- 550 - + 350,- 600 + 300,- 600 + 600,- 300 + 300,- 600 - + 600,- 300 + 300,- 600 + 600,- 300 + 300,- 600 - + 300,- 600 + 600,- 300 + 600,- 300 + 350,- 550 - + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 600 - + 350,- 550 + 350,- 550 + 350,- 550 + 600,- 350 - + 600,- 300 + 300,- 600 + 300,- 600 + 600,- 300 - + 300,- 600 + 600,- 300 + 300,- 600 + 600,- 300 + + 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 +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 - + 300,- 600 + 350,- 550 + 600,- 300 + 600,- 300 - + 600,- 300 + 300,- 600 + 600,- 300 + 600 -Sum: 47550 + + 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 + +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, , ); +rawData[18]: + -1092450 + +5950,- 500 + +1500,- 500 + 500,-1450 + 550,-1450 +1550,- 450 + + 550,-1450 + 550,-1450 + 550,-1450 + 550 +Sum: 20950 -Send generic 32 bit PulseWidth 0x87654321 LSB first +Send Sony12 as PulseWidth LSB first +Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first +Send with: IrSender.sendSony(0x11, 0x76, 2, 12); +rawData[26]: + -1036550 + +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 + +Send 32 bit PulseWidth 0x87654321 LSB first Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first -Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1050, 500, 650, 250, 350, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); rawData[66]: - -1088600 - + 950,- 550 - + 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250 - + 350,- 300 + 600,- 300 + 300,- 300 + 300,- 300 - + 650,- 250 + 650,- 250 + 300,- 300 + 350,- 250 - + 350,- 300 + 300,- 300 + 600,- 300 + 300,- 300 + -1036150 + +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,- 300 + 350,- 250 + 600,- 300 + 350,- 250 - + 350,- 300 + 600,- 300 + 600,- 300 + 300,- 300 - + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 300 - + 300,- 300 + 300,- 300 + 350,- 250 + 650 -Sum: 24500 + + 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 -Send MagiQuest 0x6BCDFF00, 0x176 as generic 55 bit PulseDistanceWidth MSB first +Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); rawData[112]: - -1089000 - + 350,- 800 + 350,- 800 + 350,- 800 + 300,- 850 - + 300,- 850 + 300,- 850 + 300,- 850 + 350,- 800 + -1065600 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550 - + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550 - + 600,- 550 + 350,- 800 + 300,- 850 + 550,- 600 - + 600,- 550 + 300,- 850 + 600,- 550 + 600,- 550 - + 600,- 550 + 600,- 600 + 550,- 550 + 600,- 550 + + 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 - + 300,- 850 + 350,- 800 + 300,- 850 + 300,- 850 - + 300,- 850 + 300,- 850 + 300,- 850 + 600,- 550 - + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550 - + 350,- 800 + 600,- 550 + 600,- 550 + 350,- 800 - + 300,- 850 + 300,- 850 + 300,- 850 + 600,- 600 - + 550,- 600 + 250,- 900 + 250,- 850 + 600 + + 350,- 850 + 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 + + 600,- 550 + 350,- 800 + 350,- 800 + 600 Sum: 63850 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); rawData[68]: - -1070700 - +8900,-4550 - + 500,-1600 + 650,- 500 + 600,- 500 + 600,- 550 - + 600,-1600 + 600,-1650 + 600,-1650 + 550,-1650 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 550,-1700 - + 550,- 550 + 600,-1650 + 550,-1650 + 600,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 500 - + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 550,- 550 + -1084150 + +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 -Sum: 76500 +Sum: 76750 Send Apple Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Send with: IrSender.sendApple(0xF1, 0x76, ); rawData[68]: - -1054650 - +8950,-4400 - + 600,- 550 + 550,-1650 + 650,-1600 + 600,-1600 - + 600,- 550 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550 - + 550,- 550 + 600,- 550 + 600,- 500 + 600,-1650 - + 600,- 550 + 550,-1650 + 600,-1650 + 600,- 500 - + 550,-1700 + 600,-1650 + 550,-1650 + 600,- 550 - + 550,-1650 + 600,- 550 + 600,- 550 + 550,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650 - + 550 -Sum: 72100 + -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 + + 600 +Sum: 72200 Send Panasonic Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); rawData[100]: - -1054300 + -1057800 +3450,-1700 - + 450,- 450 + 400,-1300 + 450,- 400 + 450,- 450 - + 450,- 400 + 450,- 450 + 400,- 450 + 450,- 400 + + 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 + 400,- 450 + 450,- 400 - + 450,- 450 + 400,- 450 + 450,- 400 + 450,- 450 - + 450,-1250 + 450,- 400 + 450,- 450 + 450,- 400 - + 450,-1300 + 400,-1300 + 450,-1300 + 400,-1300 - + 450,-1300 + 400,-1300 + 450,-1300 + 400,-1300 - + 450,- 450 + 450,-1250 + 500,-1250 + 450,- 400 - + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450 - + 450,-1250 + 450,- 450 + 450,- 400 + 450,-1300 - + 400,-1300 + 450,- 400 + 450,- 450 + 450,-1250 + + 450,- 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 + 450 Sum: 64400 @@ -342,101 +320,101 @@ Send Kaseikyo with 0x4711 as Vendor ID Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); rawData[100]: - -1074550 - +3400,-1750 + -1078000 + +3450,-1700 + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 450 - + 400,-1300 + 450,- 400 + 450,- 450 + 450,- 400 - + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450 + + 450,-1250 + 450,- 400 + 500,- 400 + 450,- 400 + + 450,-1300 + 450,-1250 + 450,-1300 + 450,- 400 + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 450 - + 400,-1300 + 450,-1300 + 400,- 450 + 450,- 400 - + 450,-1300 + 450,- 400 + 450,- 450 + 400,- 450 - + 450,-1250 + 400,-1350 + 450,-1300 + 400,-1350 - + 400,-1300 + 400,-1300 + 450,-1300 + 450,-1250 - + 450,- 450 + 400,-1300 + 450,-1300 + 400,- 450 - + 450,-1250 + 450,-1300 + 400,-1300 + 450,- 400 - + 450,- 450 + 450,-1250 + 450,- 400 + 450,-1300 - + 450,-1250 + 450,- 400 + 450,- 450 + 450,-1250 - + 450 -Sum: 69500 + + 450,-1250 + 450,-1300 + 450,- 400 + 450,- 400 + + 500,-1250 + 450,- 400 + 450,- 450 + 450,- 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 Send Kaseikyo_Denon variant Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, ); rawData[100]: - -1067700 - +3400,-1750 - + 450,- 400 + 450,- 450 + 450,-1250 + 450,- 400 - + 450,-1300 + 450,- 400 + 450,-1300 + 400,- 450 - + 450,- 400 + 450,-1300 + 450,- 400 + 450,- 400 - + 450,-1300 + 450,-1250 + 450,- 400 + 450,- 450 - + 400,- 450 + 450,- 400 + 450,- 450 + 400,- 450 - + 450,-1250 + 450,- 450 + 450,- 400 + 450,- 400 - + 450,-1300 + 450,-1250 + 450,-1300 + 400,-1300 - + 450,-1300 + 400,-1300 + 450,-1250 + 450,-1300 - + 450,- 400 + 450,-1300 + 400,-1300 + 450,- 400 - + 450,-1300 + 400,-1300 + 450,-1300 + 400,- 450 - + 450,-1250 + 450,- 450 + 400,- 450 + 450,-1300 - + 400,-1300 + 450,- 400 + 450,- 450 + 450,-1250 - + 450 -Sum: 67700 + -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 + + 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 +Sum: 67850 Send Denon Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Send with: IrSender.sendDenon(0x11, 0x76, ); rawData[32]: - -1073050 - + 250,-1850 + 250,- 750 + 250,- 800 + 250,- 800 - + 250,-1800 + 250,- 800 + 250,-1800 + 250,-1850 - + 250,- 750 + 300,-1800 + 250,-1800 + 300,-1800 - + 250,- 750 + 300,- 750 + 300,- 750 + 250 -Sum: 23050 + -1076500 + + 300,-1750 + 300,- 750 + 300,- 750 + 300,- 750 + + 300,-1750 + 300,- 750 + 300,-1800 + 250,-1800 + + 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750 + + 300,- 750 + 300,- 750 + 300,- 750 + 300 +Sum: 23150 Send Denon/Sharp variant Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first Send with: IrSender.sendSharp(0x11, 0x76, ); rawData[32]: - -1018750 - + 300,-1750 + 300,- 750 + 250,- 800 + 250,- 800 - + 250,-1800 + 250,- 800 + 250,-1800 + 300,-1800 - + 250,- 800 + 250,-1800 + 300,-1750 + 300,-1800 - + 250,- 800 + 250,- 750 + 300,-1800 + 250 -Sum: 24100 + -1018700 + + 300,-1800 + 300,- 750 + 300,- 700 + 300,- 750 + + 300,-1800 + 250,- 750 + 300,-1800 + 250,-1800 + + 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750 + + 300,- 750 + 300,- 750 + 300,-1750 + 300 +Sum: 24150 Send Sony/SIRCS with 7 command and 5 address bits Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Send with: IrSender.sendSony(0x11, 0x76, 2, 12); rawData[26]: - -1020950 - +2400,- 650 - + 550,- 600 +1200,- 550 +1250,- 550 + 650,- 550 - +1250,- 550 +1250,- 600 +1200,- 550 +1200,- 600 - + 650,- 550 + 650,- 550 + 650,- 550 +1200 -Sum: 20950 + -1020900 + +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 Send Sony/SIRCS with 7 command and 8 address bits Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); rawData[32]: - -1032550 - +2400,- 600 - + 600,- 600 +1200,- 600 +1200,- 550 + 650,- 550 - +1200,- 600 +1200,- 650 +1200,- 550 +1200,- 600 - + 650,- 550 + 650,- 550 + 650,- 550 +1200,- 600 - +1200,- 600 +1250,- 600 +1200 -Sum: 26400 + -1036650 + +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,- 550 + +1250,- 550 +1250,- 550 +1250 +Sum: 26450 Send Sony/SIRCS with 7 command and 13 address bits Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20); rawData[42]: - -1036350 - +2300,- 650 - + 600,- 600 +1200,- 550 +1250,- 550 + 650,- 600 - +1200,- 550 +1250,- 550 +1200,- 600 +1250,- 600 - + 600,- 600 + 600,- 600 + 600,- 550 +1200,- 600 - +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 600 - +1200,- 550 +1200,- 600 +1250,- 600 +1200 -Sum: 35350 + -1040400 + +2400,- 550 + + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + + 650,- 550 + 600,- 600 + 650,- 550 +1250,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 +1250 +Sum: 35400 Send Samsung 8 bit command and 8 bit address Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first @@ -444,221 +422,227 @@ Send with: IrSender.sendSamsung(0xF1, 0x76, ); rawData[68]: -1045200 +4500,-4400 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,- 500 + 650,- 450 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,- 500 + 650,- 450 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650 -Sum: 65600 + + 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 Send Samsung 16 bit command and address Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); rawData[68]: -1060350 - +4500,-4400 - + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 - + 600,-1600 + 600,-1650 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550 - + 600,-1600 + 650,-1600 + 600,-1650 + 650,- 450 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,-1600 + 600,- 550 + 600,- 500 + 650,-1600 - + 650 + +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 Send Samsung48 16 bit command Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); rawData[100]: - -1060200 - +4550,-4350 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 - + 650 -Sum: 95900 + -1060250 + +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,- 500 + 600,-1650 + 600,-1650 + 600,- 500 + + 600 +Sum: 95800 Send RC5 Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x36, ); rawData[20]: - -1073300 + -1076800 + 900,- 900 - +1750,-1800 +1750,- 900 + 900,- 850 + 900,-1750 - + 900,- 900 + 900,- 850 +1800,-1800 + 900,- 850 + +1800,-1750 +1800,- 850 + 950,- 850 + 900,-1750 + + 900,- 850 + 950,- 850 +1800,-1750 + 900,- 900 +1800 -Sum: 23100 +Sum: 23150 Send RC5X with 7.th MSB of command set Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Send with: IrSender.sendRC5(0x11, 0x76, ); rawData[20]: - -1031250 - +1800,-1750 - + 850,- 900 +1800,- 850 + 900,- 900 + 900,-1750 - + 900,- 900 + 850,- 900 +1750,-1800 + 900,- 850 + -1035650 + +1800,-1700 + + 950,- 850 +1800,- 850 + 950,- 850 + 900,-1750 + + 950,- 850 + 900,- 850 +1800,-1750 + 950,- 850 +1800 -Sum: 23050 +Sum: 23100 Send RC6 Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Send with: IrSender.sendRC6(0xF1, 0x76, ); rawData[36]: - -1028550 - +2650,- 900 - + 450,- 900 + 450,- 450 + 450,- 450 + 450,- 850 - +1350,- 450 + 450,- 450 + 450,- 450 + 450,- 900 - + 450,- 450 + 450,- 450 + 900,- 900 + 900,- 450 - + 450,- 450 + 450,- 900 + 850,- 450 + 450,- 900 - + 450 -Sum: 23250 + -1033000 + +2650,- 850 + + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850 + +1350,- 450 + 450,- 400 + 500,- 400 + 500,- 850 + + 500,- 400 + 500,- 400 + 950,- 850 + 950,- 400 + + 500,- 400 + 500,- 850 + 950,- 400 + 500,- 850 + + 500 +Sum: 23300 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! +- 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 + -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=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 +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 + -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 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 +Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); rawData[112]: - -1088750 + -1088700 + 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 + + 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 + 350,- 800 + 600,- 550 + 600,- 550 + + 600,- 550 + 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 + + 350,- 800 + 600,- 550 + 600,- 550 + 600 +Sum: 63850 Send next protocols with IrSender.write Send JVC -Protocol=JVC Address=0xF2 Command=0x87 Raw-Data=0x87F2 16 bits LSB first -Send with: IrSender.sendJVC(0xF2, 0x87, ); +Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first +Send with: IrSender.sendJVC(0xF1, 0x76, ); rawData[36]: - -1085350 + -1085250 +8400,-4150 - + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 - + 550,-1550 + 550,-1550 + 550,-1550 + 550,-1500 - + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 - + 550,- 500 + 600,- 450 + 600,- 450 + 600,-1500 - + 600 -Sum: 39350 + + 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 Send LG -Protocol=LG Address=0xF2 Command=0xA987 Raw-Data=0xF2A9872 28 bits MSB first -Send with: IrSender.sendLG(0xF2, 0xA987, ); +Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first +Send with: IrSender.sendLG(0xF1, 0x9876, ); rawData[60]: - -1039400 - +8900,-4150 - + 550,-1550 + 500,-1550 + 600,-1500 + 550,-1500 - + 550,- 500 + 550,- 500 + 600,-1500 + 550,- 500 - + 550,-1500 + 550,- 500 + 550,-1550 + 550,- 500 - + 550,-1500 + 550,- 500 + 550,- 550 + 550,-1500 - + 550,-1550 + 550,- 500 + 550,- 450 + 600,- 450 - + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 - + 550,- 500 + 550,- 500 + 550,-1500 + 550,- 500 + -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 + + 500,- 550 + 500,-1550 + 550,-1550 + 500,- 550 + + 500,-1550 + 550,-1550 + 500,-1550 + 550,- 500 + 550 -Sum: 57350 +Sum: 59400 Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first -Send with: IrSender.sendBoseWave(0x0, 0x87, ); +Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first +Send with: IrSender.sendBoseWave(0x0, 0x76, ); rawData[36]: -1056200 +1050,-1450 - + 550,-1400 + 600,-1400 + 550,-1400 + 600,- 400 - + 600,- 400 + 550,- 450 + 550,- 400 + 600,-1400 - + 600,- 400 + 600,- 400 + 550,- 400 + 600,-1400 - + 600,-1400 + 550,-1400 + 600,-1400 + 600,- 400 + + 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 Sum: 26800 Send FAST -Protocol=FAST Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first -Send with: IrSender.sendFAST(0x0, 0x87, ); +Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first +Send with: IrSender.sendFAST(0x0, 0x76, ); rawData[36]: -1040250 +2150,-1000 - + 550,-1550 + 550,-1500 + 600,-1550 + 550,- 500 - + 550,- 500 + 600,- 450 + 600,- 450 + 600,-1500 - + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 - + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 - + 600 + + 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 Force buffer overflow by sending 280 marks and spaces Overflow -Try to increase the "RAW_BUFFER_LENGTH" value of 150 in ../src/UnitTest.cpp -rawData[150]: - -1040000 - + 250,- 500 - + 200,- 600 + 200,- 550 + 200,- 500 + 200,- 550 - + 200,- 550 + 250,- 500 + 250,- 550 + 200,- 550 - + 250,- 500 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,-1300 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 250,- 500 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 500 + 250,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 500 + 250,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 550 + 200,- 550 + 200,- 550 - + 200,- 550 + 250,- 500 + 200,- 550 + 200,- 550 - + 200,- 550 + 200,- 500 + 250,- 550 + 200,- 500 - + 250,- 550 + 200,- 550 + 250,- 500 + 200,- 550 - + 200,- 550 + 200 -Sum: 56500 +Try to increase the "RAW_BUFFER_LENGTH" value of 200 in ../src/UnitTest.cpp +rawData[200]: + -1039500 + + 200,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 500 + + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 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 + + 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 + + 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 +Sum: 74500 ERROR: Unknown protocol @@ -669,99 +653,184 @@ Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first 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 + +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,- 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 + + 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: 67850 +Sum: 67800 Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first 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 + + 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,- 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,- 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: 67800 +Sum: 67750 Send NEC with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); rawData[68]: - -998700 - +8900,-4400 + -1060150 + +8900,-4450 + 600,- 500 + 600,-1650 + 600,- 550 + 600,- 500 - + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650 - + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600 + + 600,-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,-1600 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500 + + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600 + + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500 + 600 -Sum: 67650 +Sum: 67800 Send NEC2 with 16 bit address Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Send with: IrSender.sendNEC(0xF2, 0x87, ); rawData[68]: - -1055100 - +8950,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,- 500 + 650,-1600 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + -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,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1600 + + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500 + 600 -Sum: 67800 +Sum: 67750 Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Send with: IrSender.sendOnkyo(0xF2, 0x8887, ); rawData[68]: - -1053400 - +8850,-4400 - + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550 - + 600,-1600 + 600,-1650 + 600,-1650 + 550,-1650 - + 600,- 550 + 550,- 550 + 650,- 500 + 550,- 550 - + 600,- 550 + 600,- 500 + 600,- 550 + 550,- 550 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 550 - + 550,- 550 + 600,- 550 + 550,- 550 + 600,-1650 - + 600,- 500 + 600,- 550 + 550,- 550 + 600,-1650 - + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650 + -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: 62050 +Sum: 62150 Send Apple Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Send with: IrSender.sendApple(0xF2, 0x87, ); rawData[68]: - -1054100 - +8900,-4450 - + 550,- 550 + 600,-1650 + 600,-1650 + 600,-1650 - + 550,- 550 + 600,-1650 + 550,-1650 + 600,-1650 - + 600,-1650 + 600,-1650 + 550,-1650 + 600,- 550 - + 600,- 500 + 600,- 600 + 550,- 500 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,- 500 - + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 - + 550,- 550 + 600,-1650 + 550,- 550 + 600,- 550 - + 550,-1650 + 600,-1650 + 600,-1650 + 550,-1650 - + 600 -Sum: 71000 + -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 + +Send Panasonic +Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first +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 + + 500 +Sum: 59350 + +Send Kaseikyo with 0x4711 as Vendor ID +Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F23 48 bits LSB first +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 + + 450 +Sum: 66100 + +Send Kaseikyo_Denon variant +Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first +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 + + 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 +Sum: 62700 + +Send Denon +Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first +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 + + 300,-1750 + 300,- 750 + 300,- 750 + 300 +Sum: 22100 + +Send Denon/Sharp variant +Protocol=Sharp Address=0x12 Command=0x87 Raw-Data=0x50F2 15 bits LSB first +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 diff --git a/library.json b/library.json index 9f57770c9..eae4a2593 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git" }, - "version": "4.3.2", + "version": "4.4.0", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index 865e5c829..e235679e6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.3.2 +version=4.4.0 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 06d71bcad..18db8dc08 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -47,7 +47,7 @@ typedef enum { LG, LG2, NEC, - NEC2, /* NEC with full frame as repeat */ + NEC2, /* 10 NEC with full frame as repeat */ ONKYO, PANASONIC, KASEIKYO, @@ -57,7 +57,7 @@ typedef enum { KASEIKYO_MITSUBISHI, RC5, RC6, - SAMSUNG, + SAMSUNG, /* 20*/ SAMSUNGLG, SAMSUNG48, SHARP, @@ -67,9 +67,10 @@ typedef enum { BOSEWAVE, LEGO_PF, MAGIQUEST, - WHYNTER, + WHYNTER, /* 30 */ FAST } decode_type_t; +extern const char *const ProtocolNames[]; // The array of name strings for the decode_type_t enum #define SIRCS_12_PROTOCOL 12 #define SIRCS_15_PROTOCOL 15 @@ -142,9 +143,9 @@ struct PulseDistanceWidthProtocolConstants { /* * Definitions for member PulseDistanceWidthProtocolConstants.Flags */ -#define SUPPRESS_STOP_BIT_FOR_THIS_DATA 0x20 // Stop bit is otherwise sent for all pulse distance protocols. -#define PROTOCOL_IS_MSB_FIRST IRDATA_FLAGS_IS_MSB_FIRST -#define PROTOCOL_IS_LSB_FIRST IRDATA_FLAGS_IS_LSB_FIRST +#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 /* * Carrier frequencies for various protocols diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 2e444c455..55b1bc0a9 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -50,11 +50,6 @@ //#define _IR_MEASURE_TIMING // for ISR //#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start() // -/* - * Check for additional required characteristics of timing like length of mark for a constant mark protocol, - * where space length determines the bit value. Requires up to 194 additional bytes of program memory. - */ -//#define DECODE_STRICT_CHECKS /** \addtogroup Receiving Receiving IR data for multiple protocols * @{ */ @@ -685,33 +680,91 @@ bool IRrecv::decode() { * Common decode functions **********************************************************************************************************************/ /** - * Decode pulse distance width protocols. + * Decode pulse distance width protocols. We only check the mark or space length of a 1, otherwise we always assume a 0! * * We can have the following protocol timings - * Pulse distance: Pulses/marks are constant, pause/spaces have different length, like NEC. - * Pulse width: Pulses/marks have different length, pause/spaces are constant, like Sony. - * Pulse distance width: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. - * Pulse distance width can be decoded like pulse width decoder, if this decoder does not check the length of pause/spaces. + * 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. * * Input is IrReceiver.decodedIRData.rawDataPtr->rawbuf[] * Output is IrReceiver.decodedIRData.decodedRawData * - * Assume pulse distance if aOneMarkMicros == aZeroMarkMicros + * 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 Taken as constant BitMarkMicros for pulse distance. - * @param aZeroMarkMicros Not required if DECODE_STRICT_CHECKS is not defined. - * @param aOneSpaceMicros Taken as (constant) BitSpaceMicros for pulse width. - * @param aZeroSpaceMicros Not required if DECODE_STRICT_CHECKS is not defined. + * @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 */ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, - uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) { + uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) { auto *tRawBufPointer = &decodedIRData.rawDataPtr->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 + + 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) { + /* + * 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 + + } 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 + tRawBufPointer++; + } + + if (aMSBfirst) { + tDecodedData <<= 1; + } + + if (tBitValue) { + // It's a 1 -> set the bit + if (aMSBfirst) { + tDecodedData |= 1; + } else { + tDecodedData |= tMask; + } + IR_TRACE_PRINTLN(F("=> 1")); + } else { + // do not set the bit + IR_TRACE_PRINTLN(F("=> 0")); + } + tMask <<= 1; + } + decodedIRData.decodedRawData = tDecodedData; + return true; +} + +/* + * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter + */ +bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, + uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) { + + (void) aZeroSpaceMicros; + auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset]; bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop @@ -727,19 +780,78 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy /* * Pulse distance here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration. */ -#if defined DECODE_STRICT_CHECKS - tMarkTicks = *tRawBufPointer++; -#else + (void) aZeroSpaceMicros; tRawBufPointer++; -#endif + 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. + */ + tMarkTicks = *tRawBufPointer++; + tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 + tRawBufPointer++; + } + + if (aMSBfirst) { + tDecodedData <<= 1; + } + + if (tBitValue) { + // It's a 1 -> set the bit + if (aMSBfirst) { + tDecodedData |= 1; + } else { + tDecodedData |= tMask; + } + IR_TRACE_PRINTLN(F("=> 1")); + } else { + // do not set the bit + IR_TRACE_PRINTLN(F("=> 0")); + } + tMask <<= 1; + } + decodedIRData.decodedRawData = tDecodedData; + return true; +} + +/* + * 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 + * + * 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) { + + auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset]; + + bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> 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 + + 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) { + /* + * PULSE_DISTANCE here, it is not required to check constant mark duration (aOneMarkMicros) and 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 -#if defined DECODE_STRICT_CHECKS // Check for constant length mark if (!matchMark(tMarkTicks, aOneMarkMicros)) { -# if defined(LOCAL_DEBUG) +#if defined(LOCAL_DEBUG) Serial.print(F("Mark=")); Serial.print(tMarkTicks * MICROS_PER_TICK); Serial.print(F(" is not ")); @@ -747,25 +859,19 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy Serial.print(F(". Index=")); Serial.print(aNumberOfBits - i); Serial.print(' '); -# endif +#endif return false; } -#endif } else { /* - * Pulse width here, it is not required to check (constant) space duration and zero mark duration. + * 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. */ tMarkTicks = *tRawBufPointer++; tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 - -#if defined DECODE_STRICT_CHECKS tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) -#else - (void) aZeroMarkMicros; - (void) aZeroSpaceMicros; - tRawBufPointer++; -#endif } if (aMSBfirst) { @@ -781,13 +887,13 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } IR_TRACE_PRINTLN(F("=> 1")); } else { -#if defined DECODE_STRICT_CHECKS /* - * Additionally check length of length parameter which determine a zero + * 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) +#if defined(LOCAL_DEBUG) Serial.print(F("Space=")); Serial.print(tSpaceTicks * MICROS_PER_TICK); Serial.print(F(" is not ")); @@ -797,12 +903,12 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy Serial.print(F(". Index=")); Serial.print(aNumberOfBits - i); Serial.print(' '); -# endif +#endif return false; } } else { if (!matchMark(tMarkTicks, aZeroMarkMicros)) { -# if defined(LOCAL_DEBUG) +#if defined(LOCAL_DEBUG) Serial.print(F("Mark=")); Serial.print(tMarkTicks * MICROS_PER_TICK); Serial.print(F(" is not ")); @@ -812,21 +918,19 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy Serial.print(F(". Index=")); Serial.print(aNumberOfBits - i); Serial.print(' '); -# endif +#endif return false; } } -#endif // do not set the bit IR_TRACE_PRINTLN(F("=> 0")); } -#if defined DECODE_STRICT_CHECKS // If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it 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) +#if defined(LOCAL_DEBUG) Serial.print(F("Space=")); Serial.print(tSpaceTicks * MICROS_PER_TICK); Serial.print(F(" is not ")); @@ -834,11 +938,10 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy Serial.print(F(". Index=")); Serial.print(aNumberOfBits - i); Serial.print(' '); -# endif +#endif return false; } } -#endif tMask <<= 1; } decodedIRData.decodedRawData = tDecodedData; @@ -853,8 +956,8 @@ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a IRRawlenType aStartOffset) { return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, - aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, - aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aProtocolConstants->Flags); + aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, + aProtocolConstants->Flags); } /* @@ -1053,6 +1156,7 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTick /** * 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) { @@ -1081,6 +1185,7 @@ bool MATCH(uint16_t measured_ticks, uint16_t desired_us) { /** * Compensate for marks exceeded by demodulator hardware + * @return true, if values match */ bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { #if defined(LOCAL_TRACE) @@ -1114,6 +1219,7 @@ bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) { /** * Compensate for spaces shortened by demodulator hardware + * @return true, if values match */ bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { #if defined(LOCAL_TRACE) @@ -1388,8 +1494,8 @@ void IRrecv::printIRSendUsage(Print *aSerial) { #if defined(DECODE_DISTANCE_WIDTH) if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) { #endif - aSerial->print(getProtocolString()); - aSerial->print(F("(0x")); + aSerial->print(getProtocolString()); + aSerial->print(F("(0x")); #if defined(DECODE_MAGIQUEST) if (decodedIRData.protocol == MAGIQUEST) { # if (__INT_WIDTH__ < 32) @@ -1401,20 +1507,20 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(decodedIRData.address, HEX); } #else - /* - * New decoders have address and command - */ - aSerial->print(decodedIRData.address, HEX); + /* + * New decoders have address and command + */ + aSerial->print(decodedIRData.address, HEX); #endif - aSerial->print(F(", 0x")); - aSerial->print(decodedIRData.command, HEX); - if (decodedIRData.protocol == SONY) { - aSerial->print(F(", 2, ")); - aSerial->print(decodedIRData.numberOfBits); - } else { - aSerial->print(F(", ")); - } + 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_DISTANCE_WIDTH) } else { diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 532ac03f0..470c64790 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -521,7 +521,7 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf * For LSB First the LSB of array[0] is sent first then all bits until MSB of array[0]. Next is LSB of array[1] and so on. * The output always ends with a space * Stop bit is always sent - * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. + * @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, @@ -575,7 +575,7 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_ } else { // intermediate data tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; - tFlags = aFlags | SUPPRESS_STOP_BIT_FOR_THIS_DATA; // No stop bit for leading data + tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray[i], @@ -655,7 +655,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants } else { // intermediate data tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; - tFlags = tOriginalFlags | SUPPRESS_STOP_BIT_FOR_THIS_DATA; // No stop bit for leading data + tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, @@ -750,7 +750,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc * @param aFrequencyKHz, aHeaderMarkMicros, aHeaderSpaceMicros, aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aFlags, aRepeatPeriodMillis Values to use for sending this protocol, also contained in the PulseDistanceWidthProtocolConstants of this protocol. * @param aData uint32 or uint64 holding the bits to be sent. * @param aNumberOfBits Number of bits from aData to be actually sent. - * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. + * @param 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 NULL, the first frame is repeated completely, otherwise this function is used for sending the repeat frame. @@ -823,7 +823,7 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr * @param aOneMarkMicros Timing for sending this protocol. * @param aData uint32 or uint64 holding the bits to be sent. * @param aNumberOfBits Number of bits from aData to be actually sent. - * @param aFlags Evaluated flags are PROTOCOL_IS_MSB_FIRST and SUPPRESS_STOP_BIT_FOR_THIS_DATA. Stop bit is otherwise sent for all pulse distance protocols. + * @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) { @@ -858,16 +858,16 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp } } /* - * Stop bit is sent for all pulse distance protocols i.e. aOneMarkMicros == aZeroMarkMicros. - * Therefore it is not sent for Sony and Magiquest :-) - * For sending from an array, no intermediate stop bit must be sent for first data chunk. + * 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_FOR_THIS_DATA) && aOneMarkMicros == aZeroMarkMicros) { + if ((!(aFlags & SUPPRESS_STOP_BIT)) && (abs(aOneSpaceMicros - aZeroSpaceMicros) > (aOneSpaceMicros / 4))) { // Send stop bit here #if defined(LOCAL_TRACE) Serial.print('S'); #endif - mark(aZeroMarkMicros); // Use aZeroMarkMicros for stop bits. This seems to be correct for all protocols :-) + mark(aOneMarkMicros); // Use aOneMarkMicros for stop bits. This seems to be correct for all protocols :-) } #if defined(LOCAL_TRACE) Serial.println(); diff --git a/src/IRVersion.h b/src/IRVersion.h index 0ad8d7bfa..668bb9a14 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -6,7 +6,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2015-2023 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer + * Copyright (c) 2015-2024 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,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.3.2" +#define VERSION_IRREMOTE "4.4.0" #define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 3 -#define VERSION_IRREMOTE_PATCH 2 +#define VERSION_IRREMOTE_MINOR 4 +#define VERSION_IRREMOTE_PATCH 0 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index cecdfb0d7..6439485ce 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -264,6 +264,13 @@ class IRrecv { IRRawlenType aStartOffset = 3); bool 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, + 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 decodeBiPhaseData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint_fast8_t aStartClockCount, @@ -384,22 +391,21 @@ void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please us * First MARK is the one after the long gap * Pulse parameters in microseconds */ -#if !defined(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) -#define TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING 25 // Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. +#if !defined(TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT) +#define TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT 25 // Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding. #endif -//#define TICKS_LOW(us) ((int)(((us)*LTOL/MICROS_PER_TICK))) -//#define TICKS_HIGH(us) ((int)(((us)*UTOL/MICROS_PER_TICK + 1))) -#if MICROS_PER_TICK == 50 && TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING == 25 // Defaults -#define TICKS_LOW(us) ((us)/67 ) // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100) -#define TICKS_HIGH(us) (((us)/40) + 1) // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1 +#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) #else /** Lower tolerance for comparison of measured data */ //#define LTOL (1.0 - (TOLERANCE/100.)) -#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) +#define LTOL (100 - TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT) /** Upper tolerance for comparison of measured data */ //#define UTOL (1.0 + (TOLERANCE/100.)) -#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING) +#define UTOL (100 + TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT) #define TICKS_LOW(us) ((uint16_t ) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) )) #define TICKS_HIGH(us) ((uint16_t ) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1)) #endif diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index 1029e262e..60cd65a9f 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -293,8 +293,8 @@ bool IRrecv::decodeDenonOld(decode_results *aResults) { return false; } - // Try to decode as Denon protocol - if (!decodePulseDistanceWidthData(DENON_BITS, 3, DENON_BIT_MARK, 0, DENON_ONE_SPACE, DENON_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) { + // Try to decode as Denon protocol. + if (!decodePulseDistanceWidthData(DENON_BITS, 3, DENON_BIT_MARK, DENON_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { return false; } diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 67233901a..5744dc679 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -90,6 +90,34 @@ // DDD III SSSS TT A A N N CCC EEEE W W III DDD TT H H //===================================================================================== // see: https://www.mikrocontroller.net/articles/IRMP_-_english#Codings +/* + Example output of UnitTest.ino for PulseWidth protocol: + Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first + Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); + rawData[66]: + -1088600 + + 950,- 550 + + 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250 + + 350,- 300 + 600,- 300 + 300,- 300 + 300,- 300 + + 650,- 250 + 650,- 250 + 300,- 300 + 350,- 250 + + 350,- 300 + 300,- 300 + 600,- 300 + 300,- 300 + + 600,- 300 + 350,- 250 + 600,- 300 + 350,- 250 + + 350,- 300 + 600,- 300 + 600,- 300 + 300,- 300 + + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 300 + + 300,- 300 + 300,- 300 + 350,- 250 + 650 + Sum: 24500 + + Example output of UnitTest.ino for PulseDistanceWidth protocol: + 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, , ); + rawData[18]: + -1092450 + +5950,- 500 + +1500,- 500 + 500,-1450 + 550,-1450 +1550,- 450 + + 550,-1450 + 550,-1450 + 550,-1450 + 550 + Sum: 20950 + */ + #if defined(LOCAL_DEBUG) void printDurations(uint8_t aArray[], uint8_t aMaxIndex) { for (uint_fast8_t i = 0; i <= aMaxIndex; i++) { @@ -116,11 +144,13 @@ void printDurations(uint8_t aArray[], uint8_t aMaxIndex) { #endif /* + * We count all consecutive (allow only one gap between) durations and compute the average. * @return false if more than 2 distinct duration values found */ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIndex, uint8_t *aLongIndex) { uint8_t tSum = 0; uint16_t tWeightedSum = 0; + uint8_t tGapCount = 0; for (uint_fast8_t i = 0; i <= aMaxIndex; i++) { uint8_t tCurrentDurations = aArray[i]; if (tCurrentDurations != 0) { @@ -128,9 +158,14 @@ bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIn tSum += tCurrentDurations; tWeightedSum += (tCurrentDurations * i); aArray[i] = 0; + tGapCount = 0; + } else { + tGapCount++; } - if ((tCurrentDurations == 0 || i == aMaxIndex) && tSum != 0) { - // here we have a sum and a gap after the values + if (tSum != 0 && (i == aMaxIndex || tGapCount > 1)) { + /* + * Here we have a sum AND last element OR more than 1 consecutive gap + */ uint8_t tAggregateIndex = (tWeightedSum + (tSum / 2)) / tSum; // with rounding aArray[tAggregateIndex] = tSum; // disabling this line increases code size by 2 - unbelievable! // store aggregate for later decoding @@ -167,13 +202,13 @@ bool IRrecv::decodeDistanceWidth() { uint8_t tDurationArray[DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE]; /* - * Accept only protocols with at least 8 bits + * Accept only protocols with at least 7 bits */ - if (decodedIRData.rawlen < (2 * 8) + 4) { + 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 20")); + IR_DEBUG_PRINTLN(F(" is less than 18")); return false; } @@ -272,7 +307,7 @@ bool IRrecv::decodeDistanceWidth() { } /* - * Print characteristics of this protocol. Durations are in ticks. + * 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 @@ -281,6 +316,8 @@ bool IRrecv::decodeDistanceWidth() { * 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 + * 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: ")); @@ -302,8 +339,8 @@ bool IRrecv::decodeDistanceWidth() { uint16_t tNumberOfBits; #endif tNumberOfBits = (decodedIRData.rawlen / 2) - 1; - if (tSpaceTicksLong > 0 && tMarkTicksLong == 0) { - // For PULSE_DISTANCE a stop bit is mandatory, for PULSE_WIDTH it is not required! + 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; @@ -311,10 +348,9 @@ bool IRrecv::decodeDistanceWidth() { /* * We can have the following protocol timings - * Pulse distance: Pulses/marks are constant, pause/spaces have different length, like NEC. - * Pulse width: Pulses/marks have different length, pause/spaces are constant, like Sony. - * Pulse distance width: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. - * Pulse distance width can be decoded by pulse width decoder, if this decoder does not check the length of pause/spaces. + * 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. */ if (tMarkTicksLong == 0 && tSpaceTicksLong == 0) { @@ -346,13 +382,14 @@ bool IRrecv::decodeDistanceWidth() { tNumberOfBitsForOneDecode = BITS_IN_RAW_DATA_TYPE; } bool tResult; - if (tMarkTicksLong > 0) { + if (tSpaceTicksLong > 0) { /* - * Here short and long mark durations found. + * Here short and long space durations found. + * Since parameters aOneMarkMicros and aOneSpaceMicros are equal, we only check tSpaceMicrosLong here. */ - decodedIRData.protocol = PULSE_WIDTH; - tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong, tMarkMicrosShort, - tSpaceMicrosShort, 0, + decodedIRData.protocol = PULSE_DISTANCE; // Sony + PULSE_DISTANCE_WIDTH + tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosShort, tSpaceMicrosLong, + tMarkMicrosShort, #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) true #else @@ -361,17 +398,19 @@ bool IRrecv::decodeDistanceWidth() { ); } else { /* - * Here short and long space durations found. + * Here no long space duration found. => short and long mark durations found, check tMarkMicrosLong here + * This else case will most likely never be used, but it only requires 12 bytes additional programming space :-) */ - decodedIRData.protocol = PULSE_DISTANCE; - tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosShort, tMarkMicrosShort, - tSpaceMicrosLong, tSpaceMicrosShort, + decodedIRData.protocol = PULSE_WIDTH; // NEC etc. + tResult = decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong, tSpaceMicrosShort, + tMarkMicrosShort, #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) true #else false #endif ); + } if (!tResult) { #if defined(LOCAL_DEBUG) @@ -406,17 +445,25 @@ bool IRrecv::decodeDistanceWidth() { decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosShort; decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosShort; if (tMarkMicrosLong != 0) { - decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong; - - decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort; - if (tSpaceMicrosLong != 0) { - // Assume long space for zero when we have PulseDistanceWidth -> enables constant bit length - decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosLong; + if (tSpaceMicrosLong == 0) { + // PULSE_DISTANCE, Sony + decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong; + decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort; + } else { + // PULSE_DISTANCE_WIDTH, we have 4 distinct values here + // Assume long space for a one when we have PulseDistanceWidth like for RS232, where a long inactive period (high) is a 1 + decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosLong; + decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort; + decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosLong; +// // Assume long mark for a one when we have PulseDistanceWidth +// decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort; +// decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosLong; +// decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong; } } else { - decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort; - + // PULSE_WIDTH, NEC etc. // Here tMarkMicrosLong is 0 => tSpaceMicrosLong != 0 + decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort; decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosLong; } diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 6267fb0f6..c827859f8 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -207,7 +207,7 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(JVC_BITS, offset, JVC_BIT_MARK, 0, JVC_ONE_SPACE, JVC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) { + if (!decodePulseDistanceWidthData(JVC_BITS, offset, JVC_BIT_MARK, JVC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { return false; } diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 572838cf0..52df1dbd0 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -306,7 +306,7 @@ bool IRrecv::decodeLGMSB(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(LG_BITS, offset, LG_BIT_MARK, 0, LG_ONE_SPACE, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) { + if (!decodePulseDistanceWidthData(LG_BITS, offset, LG_BIT_MARK, LG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { return false; } // Stop bit diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index d3941cd70..291f80869 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -14,7 +14,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2017-2023 E. Stuart Hicks , Armin Joachimsmeyer + * Copyright (c) 2017-2024 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 @@ -79,6 +79,8 @@ // Checksum (+ sum of the 5 bytes before == 0) + 250,- 900 + 300,- 900 + 250,- 850 + 550,- 600 + 600,- 550 + 300,- 900 + 250,- 850 + 550 + + // No stop bit! */ // MSB first, 8 start bits (zero), 31 wand id bits, 9 magnitude bits 8 checksum bits and no stop bit => 56 bits #define MAGIQUEST_CHECKSUM_BITS 8 // magiquest_t.cmd.checksum @@ -108,7 +110,8 @@ // 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, 110, NULL }; +MAGIQUEST_ONE_MARK, MAGIQUEST_ONE_SPACE, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | SUPPRESS_STOP_BIT, 110, + NULL }; //+============================================================================= // /** diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 8d59d06b9..b02931cc7 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -380,7 +380,7 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(NEC_BITS, offset, NEC_BIT_MARK, 0, NEC_ONE_SPACE, NEC_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST)) { + if (!decodePulseDistanceWidthData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { #if defined(LOCAL_DEBUG) Serial.print(F("NEC MSB: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 154b74b21..eaa6e921b 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -393,8 +393,7 @@ bool IRrecv::decodeSAMSUNG(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, 0, SAMSUNG_ONE_SPACE, SAMSUNG_ZERO_SPACE, - PROTOCOL_IS_MSB_FIRST)) { + if (!decodePulseDistanceWidthData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { return false; } diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index c757e30e1..59b7a8f74 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -52,7 +52,7 @@ // 7 command bits +1300,- 450 +1350,- 450 +1300,- 450 + 700,- 450 + 700,- 450 + 750,- 450 + 700,- 400 - // (5,8,) 13 address bits + // (5,8,) 13 address bits and NO stop bit! +1300,- 500 + 700,- 450 + 700,- 450 +1300,- 500 +1300,- 450 +1300,- 450 + 700,- 450 +1350,- 400 + 750,- 450 diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 19de58ce6..0b129eb56 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1450,26 +1450,26 @@ void timerEnableReceiveInterrupt() { timerAlarmEnable(s50usTimer); } -#if !defined(ESP_ARDUINO_VERSION) +# if !defined(ESP_ARDUINO_VERSION) #define ESP_ARDUINO_VERSION 0 -#endif -#if !defined(ESP_ARDUINO_VERSION_VAL) +# endif +# if !defined(ESP_ARDUINO_VERSION_VAL) #define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202 -#endif -#if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) +# endif +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { timerDetachInterrupt(s50usTimer); timerEnd(s50usTimer); } } -#else +# else void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { timerAlarmDisable(s50usTimer); } } -#endif +# endif // Undefine ISR, because we register/call the plain function IRReceiveTimerInterruptHandler() # if defined(ISR) From dc4a137894b0c1fd6c28c7ae000b107047be434c Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 24 Jun 2024 22:22:23 +0200 Subject: [PATCH 051/133] Documentation --- README.md | 2 +- examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 6 +++--- examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp | 4 ++-- examples/IRremoteExtensionTest/IRremoteExtensionTest.ino | 4 ++-- examples/MicroGirs/MicroGirs.ino | 6 +++--- .../ReceiveAndSendDistanceWidth.ino | 6 +++--- examples/ReceiveDemo/ReceiveDemo.ino | 4 ++-- examples/ReceiveDump/ReceiveDump.ino | 6 +++--- examples/SimpleReceiver/SimpleReceiver.ino | 2 +- .../SimpleReceiverWithCallback.ino | 2 +- examples/UnitTest/UnitTest.ino | 2 +- src/IRremoteInt.h | 6 +++--- 12 files changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 4324754cb..27fc4e1c4 100644 --- a/README.md +++ b/README.md @@ -783,7 +783,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| -| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input buffer. Must be even! 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. | +| `RAW_BUFFER_LENGTH` | 100 | 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 100 requires 200 bytes, a value of 750 requires 1.5k 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. | | `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. | diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 922c356dc..f828593b6 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -38,12 +38,12 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 520 +#define RAW_BUFFER_LENGTH 520 // Requires 1040 bytes RAM #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # else -#define RAW_BUFFER_LENGTH 750 +#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 400 // The decoder accepts mark or space durations up to 400 * 50 (MICROS_PER_TICK) = 20 milliseconds # endif #endif diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 61462904c..f2bac6552 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -38,9 +38,9 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM # endif #endif diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index 7c6c3611f..a2b580e10 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -35,9 +35,9 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM # endif #endif diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index 326d22e0b..fee20a3a4 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -69,11 +69,11 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM # else -#define RAW_BUFFER_LENGTH 750 +#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM # endif #endif diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index ffe557ad8..88a897f2a 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -59,11 +59,11 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM # else -#define RAW_BUFFER_LENGTH 750 +#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM # endif #endif diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 1f0ce6f68..d0a84e965 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -75,9 +75,9 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 520 +#define RAW_BUFFER_LENGTH 520 // Requires 1040 bytes RAM #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # endif #endif diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 198ef064e..e89ea39d5 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -38,11 +38,11 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM # else -#define RAW_BUFFER_LENGTH 750 +#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM # endif #endif diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index a5153f4ec..631746d4c 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -60,7 +60,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. -//#define RAW_BUFFER_LENGTH 180 // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +//#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. #include diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index c68518cc4..17218924d 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 180 // Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +//#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. #include diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index a499fa1b1..62c2b081d 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -38,7 +38,7 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 +#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define RAW_BUFFER_LENGTH 200 // 600 is too much here, because then variables are overwritten. 500 is OK without Pronto and 200 is OK with Pronto # endif diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 6439485ce..4f95900ae 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -71,13 +71,13 @@ # if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) // for RAMsize <= 2k # if defined(DECODE_MAGIQUEST) -#define RAW_BUFFER_LENGTH 112 // MagiQuest requires 112 bytes. +#define RAW_BUFFER_LENGTH 112 // MagiQuest requires 224 bytes. # else -#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit. +#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. 100 -> 200 bytes. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit. # endif # else // For undefined or bigger RAMsize -#define RAW_BUFFER_LENGTH 750 // 750 (600 if we have only 2k RAM) is the value for air condition remotes. +#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM. The value for air condition remotes. # endif #endif #if RAW_BUFFER_LENGTH % 2 == 1 From 38bd4ddbd5f490f4bb3386c028507b5413ff2935 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 24 Jun 2024 23:09:37 +0200 Subject: [PATCH 052/133] New example SimpleReceiverForHashCodes. closes #1244 --- examples/SimpleReceiver/SimpleReceiver.ino | 4 +- .../PinDefinitionsAndMore.h | 342 ++++++++++++++++++ .../SimpleReceiverForHashCodes.ino | 90 +++++ 3 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h create mode 100644 examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 631746d4c..44ac4c759 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -31,6 +31,8 @@ ************************************************************************************ */ +#include + /* * Specify which protocol(s) should be used for decoding. * If no protocol is defined, all protocols (except Bang&Olufsen) are active. @@ -62,8 +64,6 @@ //#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -#include - /* * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures */ diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h new file mode 100644 index 000000000..37d57d93a --- /dev/null +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -0,0 +1,342 @@ +/* + * 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 + * ATtiny3217 18|PA1 19|PA2 20|PA3 MegaTinyCore + * ATtiny1604 2 3|PA5 % + * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore + * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore + * SAMD21 3 4 5 + * ESP8266 14|D5 12|D6 % + * ESP32 15 4 27 + * ESP32-C3 6 7 10 + * BluePill PA6 PA7 PA3 + * APOLLO3 11 12 5 + * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 + */ +//#define _IR_MEASURE_TIMING // For debugging purposes. + +#if defined(__AVR__) +#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Digispark board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. +#define IR_RECEIVE_PIN PIN_PB0 +#define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. +#define TONE_PIN PIN_PB3 +#define _IR_TIMING_TEST_PIN PIN_PB3 + +# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" +// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. +# if defined(ARDUINO_AVR_DIGISPARKPRO) +// For use with Digispark original core +#define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 +//#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 +#define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 +#define _IR_TIMING_TEST_PIN 10 // PA4 +# else +// For use with ATTinyCore +#define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards +#define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 +#define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 +# endif + +# elif defined(__AVR_ATtiny84__) // For use with ATTinyCore +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +#define IR_RECEIVE_PIN PIN_PB2 // INT0 +#define IR_SEND_PIN PIN_PA4 +#define TONE_PIN PIN_PA3 +#define _IR_TIMING_TEST_PIN PIN_PA5 + +# elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board. For use with ATTinyCore. +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. +// Pin 6 is TX, pin 7 is RX +#define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 +#define IR_SEND_PIN PIN_PD4 // 4 +#define TONE_PIN PIN_PB1 // 9 +#define _IR_TIMING_TEST_PIN PIN_PB0 // 8 + +# elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // For use with megaTinyCore +// Tiny Core Dev board +// https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock +// https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock +#define IR_RECEIVE_PIN PIN_PA1 // use 18 instead of PIN_PA1 for TinyCore32 +#define IR_SEND_PIN PIN_PA2 // 19 +#define TONE_PIN PIN_PA3 // 20 +#define APPLICATION_PIN PIN_PA0 // 0 +#undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output +#define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 + +# elif defined(__AVR_ATtiny816__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 14 +#define IR_SEND_PIN PIN_PA1 // 16 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 +#undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output +#define LED_BUILTIN PIN_PB5 // 4 + +# elif defined(__AVR_ATtiny1614__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA3 // 10 +#define TONE_PIN PIN_PA5 // 1 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1604__) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA6 // 2 - To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN PIN_PA7 // 3 +#define APPLICATION_PIN PIN_PB2 // 5 + +#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +# elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ +|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ +|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ +|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ +|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ +|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ +|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ +|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ +|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 13 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. +#define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +# if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit +// We have no built in LED at pin 13 -> reuse RX LED +#undef LED_BUILTIN +#define LED_BUILTIN LED_BUILTIN_RX +# endif +# endif // defined(__AVR_ATtiny25__)... + +#elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 +// To be compatible with Uno R3. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ESP8266) +#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW +#define IR_RECEIVE_PIN 14 // D5 +#define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED +#define _IR_TIMING_TEST_PIN 2 // D4 +#define APPLICATION_PIN 13 // D7 + +#define tone(...) void() // tone() inhibits receive timer +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +#define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... +#define IR_RECEIVE_PIN 6 +#define IR_SEND_PIN 7 +#define TONE_PIN 10 +#define APPLICATION_PIN 18 + +#elif defined(ESP32) +#include + +// tone() is included in ESP32 core since 2.0.2 +#if !defined(ESP_ARDUINO_VERSION_VAL) +#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 12345678 +#endif +#if ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) +#define TONE_LEDC_CHANNEL 1 // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer. +void tone(uint8_t aPinNumber, unsigned int aFrequency){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); +} +void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){ + ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL); + ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency); + delay(aDuration); + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +void noTone(uint8_t aPinNumber){ + ledcWriteTone(TONE_LEDC_CHANNEL, 0); +} +#endif // ESP_ARDUINO_VERSION <= ESP_ARDUINO_VERSION_VAL(2, 0, 2) + +#define IR_RECEIVE_PIN 15 // D15 +#define IR_SEND_PIN 4 // D4 +#define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 +#define APPLICATION_PIN 16 // RX2 pin + +#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1) // BluePill +// Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() +#define IR_RECEIVE_PIN PA6 +#define IR_RECEIVE_PIN_STRING "PA6" +#define IR_SEND_PIN PA7 +#define IR_SEND_PIN_STRING "PA7" +#define TONE_PIN PA3 +#define _IR_TIMING_TEST_PIN PA5 +#define APPLICATION_PIN PA2 +#define APPLICATION_PIN_STRING "PA2" +# if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) +// BluePill LED is active low +#define FEEDBACK_LED_IS_ACTIVE_LOW +# endif + +#elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards +#define IR_RECEIVE_PIN 11 +#define IR_SEND_PIN 12 +#define TONE_PIN 5 + +#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE 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) // !!!UNTESTED!!! +#define IR_RECEIVE_PIN A4 +#define IR_SEND_PIN A5 // Particle supports multiple pins + +#define LED_BUILTIN D7 + +/* + * 4 times the same (default) layout for easy adaption in the future + */ +#elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 + +#if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) +// On the Zero and others we switch explicitly to SerialUSB +#define Serial SerialUSB +#endif + +// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17. +// Attention!!! D2 and D4 are swapped on these boards!!! +// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 24 // PB11 +// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines. +//#undef LED_BUILTIN +//#define LED_BUILTIN 25 // PB03 +//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW + +#elif defined (NRF51) // BBC micro:bit +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define APPLICATION_PIN 1 +#define _IR_TIMING_TEST_PIN 4 + +#define tone(...) void() // no tone() available +#define noTone(a) void() +#define TONE_PIN 42 // Dummy for examples using it + +#else +#warning Board / CPU is not detected using pre-processor symbols -> using default values, which may not fit. Please extend PinDefinitionsAndMore.h. +// Default valued for unidentified boards +#define IR_RECEIVE_PIN 2 +#define IR_SEND_PIN 3 +#define TONE_PIN 4 +#define APPLICATION_PIN 5 +#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. +#define _IR_TIMING_TEST_PIN 7 +#endif // defined(ESP8266) + +#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) +#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation +#else +# if defined(SEND_PWM_BY_TIMER) +#undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp +# endif +#endif + +#if !defined (FLASHEND) +#define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined +#endif + +/* + * Helper macro for getting a macro definition as string + */ +#if !defined(STR_HELPER) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino new file mode 100644 index 000000000..49a321f3d --- /dev/null +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -0,0 +1,90 @@ +/* + * SimpleReceiverForHashCodes.cpp + * + * Demonstrates receiving hash codes of unknown protocols with IRremote + * + * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * + ************************************************************************************ + * MIT License + * + * Copyright (c) 2024 Armin Joachimsmeyer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************************ + */ + +#include + +/* + * Specify which protocol(s) should be used for decoding. + * This must be done before the #include + */ +#define DECODE_HASH // special decoder for all protocols +#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM. Especially useful for unknown and probably long protocols +//#define DEBUG // Activate this for lots of lovely debug output from the decoders. + +/* + * 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 + +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)); + + // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED + IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); + + Serial.println(F("Ready to receive unknown IR signals at pin " STR(IR_RECEIVE_PIN) " and decode it with hash decoder.")); +} + +void loop() { + /* + * Check if received data is available and if yes, try to decode it. + * Decoded hash result is in IrReceiver.decodedIRData.decodedRawData + */ + if (IrReceiver.available()) { + IrReceiver.initDecodedIRData(); // is required, if we do not call decode(); + IrReceiver.decodeHash(); + /* + * Print a summary of received data + */ + // We have an unknown protocol here, print extended info + 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 + } + } +} From 1df81952147cc2c951d076bafbf115dac62a66f8 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 26 Jun 2024 11:22:54 +0200 Subject: [PATCH 053/133] Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]) --- .github/workflows/LibraryBuild.yml | 66 ++++++++----------- README.md | 22 ++++++- changelog.md | 2 + .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 12 ++-- .../AllProtocolsOnLCD/LiquidCrystal_I2C.cpp | 4 ++ .../IRremoteExtensionClass.cpp | 6 +- .../IRremoteExtensionTest.ino | 8 +-- examples/MicroGirs/MicroGirs.ino | 8 +-- examples/ReceiveAndSend/ReceiveAndSend.ino | 10 +-- .../ReceiveAndSendDistanceWidth.ino | 8 +-- examples/ReceiveDemo/ReceiveDemo.ino | 9 +-- examples/ReceiveDump/ReceiveDump.ino | 10 +-- examples/SimpleReceiver/SimpleReceiver.ino | 2 +- .../SimpleReceiverForHashCodes.ino | 2 +- .../SimpleReceiverWithCallback.ino | 2 +- examples/UnitTest/UnitTest.ino | 8 +-- src/IRProtocol.h | 4 +- src/IRProtocol.hpp | 2 +- src/IRReceive.hpp | 40 ++++++----- src/IRremote.hpp | 9 +-- src/IRremoteInt.h | 56 ++++++++++------ src/ir_BangOlufsen.hpp | 6 +- src/ir_Denon.hpp | 2 +- src/ir_DistanceWidthProtocol.hpp | 2 +- src/ir_FAST.hpp | 3 +- src/ir_JVC.hpp | 2 +- src/ir_Lego.hpp | 2 +- src/ir_Pronto.hpp | 4 +- src/ir_RC5_RC6.hpp | 2 +- 29 files changed, 171 insertions(+), 142 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index be5dd8333..c6dbb9b0f 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -83,17 +83,17 @@ jobs: - arduino-boards-fqbn: arduino:avr:uno build-properties: # the flags were put in compiler.cpp.extra_flags ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=1200 -DIR_SEND_PIN=3 - arduino-boards-fqbn: arduino:avr:uno|DEBUG build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER All: -DEBUG - 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=100 -DIR_SEND_PIN=3 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 TinyReceiver: -DUSE_FAST_PROTOCOL TinySender: -DUSE_FAST_PROTOCOL All: -DUSE_NO_SEND_PWM @@ -101,7 +101,7 @@ jobs: - arduino-boards-fqbn: arduino:avr:uno|SEND_PWM_BY_TIMER sketches-exclude: UnitTest build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DIR_SEND_PIN=3 -DSEND_PWM_BY_TIMER + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 -DSEND_PWM_BY_TIMER ReceiveDemo: -DDECODE_ONKYO TinyReceiver: -DUSE_ONKYO_PROTOCOL TinySender: -DUSE_ONKYO_PROTOCOL @@ -109,7 +109,7 @@ 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=100 -DIR_SEND_PIN=3 -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 -DIR_SEND_PIN=3 -DUSE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN SimpleSender: -DSEND_PWM_BY_TIMER TinyReceiver: -DENABLE_NEC2_REPEATS TinySender: -DENABLE_NEC2_REPEATS @@ -117,14 +117,14 @@ jobs: - arduino-boards-fqbn: arduino:avr:mega:cpu=atmega2560 build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 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=100 + 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 @@ -132,7 +132,7 @@ jobs: - 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=100 + 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 @@ -140,22 +140,22 @@ jobs: - 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=100 + 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=700 + 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=100 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 - arduino-boards-fqbn: arduino:mbed:nano33ble build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 SimpleSender: -DSEND_PWM_BY_TIMER # @@ -163,15 +163,15 @@ jobs: # - arduino-boards-fqbn: arduino:mbed_rp2040:pico build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 SimpleSender: -DSEND_PWM_BY_TIMER - arduino-boards-fqbn: rp2040:rp2040:arduino_nano_connect platform-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=100 -DSEND_PWM_BY_TIMER + IRremoteExtensionTest: -DSEND_PWM_BY_TIMER SimpleSender: -DSEND_PWM_BY_TIMER - All: -DRAW_BUFFER_LENGTH=700 + All: -DRAW_BUFFER_LENGTH=750 # # megaTinyCore @@ -182,7 +182,7 @@ jobs: # 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=100 +# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 # https://github.com/SpenceKonde/megaTinyCore/issues/935 # - arduino-boards-fqbn: megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal @@ -190,7 +190,7 @@ jobs: # 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=100 +# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 # # ATTinyCore @@ -223,9 +223,8 @@ jobs: platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json arduino-platform: arduino:avr,MegaCore:avr # gcc is taken from arduino:avr build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=300 SimpleSender: -DSEND_PWM_BY_TIMER - All: -DRAW_BUFFER_LENGTH=700 + All: -DRAW_BUFFER_LENGTH=750 # # ESP @@ -234,24 +233,23 @@ jobs: platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json sketches-exclude: TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=200 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 - 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: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized - All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 + IRremoteExtensionTest: -Wno-error=maybe-uninitialized + All: -DRAW_BUFFER_LENGTH=750 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 - arduino-boards-fqbn: esp32:esp32:esp32c3 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json arduino-platform: esp32:esp32@2.0.17 # latest 2.x version 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: -DRAW_BUFFER_LENGTH=500 -Wno-error=maybe-uninitialized - All: -DRAW_BUFFER_LENGTH=300 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 + IRremoteExtensionTest: -Wno-error=maybe-uninitialized + All: -DRAW_BUFFER_LENGTH=750 -Wno-error=maybe-uninitialized # https://github.com/espressif/arduino-esp32/issues/7024 # # STM @@ -260,22 +258,19 @@ jobs: platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json sketches-exclude: TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 - arduino-boards-fqbn: STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072 # ST version platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json sketches-exclude: TinyReceiver,IRDispatcherDemo build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 - arduino-boards-fqbn: stm32duino:STM32F1:genericSTM32F103C # Roger Clark version platform-url: http://dan.drown.org/stm32duino/package_STM32duino_index.json sketches-exclude: TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 # # Others @@ -284,22 +279,19 @@ jobs: arduino-platform: arduino:avr,SparkFun:avr platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 - arduino-boards-fqbn: sandeepmistry:nRF5:BBCmicrobit platform-url: https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json sketches-exclude: IRDispatcherDemo,MicroGirs,TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 - 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 build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=700 - All: -DRAW_BUFFER_LENGTH=300 + All: -DRAW_BUFFER_LENGTH=750 # fail-fast: false # false -> do not cancel all jobs / architectures if one job fails diff --git a/README.md b/README.md index 27fc4e1c4..0ee428a6a 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) * [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) @@ -437,6 +438,17 @@ The **ReceiveDump example** gives you more information but has bad repeat detect 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. +- **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**. +- MAGIQUEST requires a buffer length of **112**. +- Air conditioners often send a longer protocol data stream **up to 750 bits**. + +If the record gap determined by `RECORD_GAP_MICROS` is changed from the default 8 ms to more than 20 ms, the buffer is no longer a byte but a uint16_t buffer, requiring twice as much RAM.
# Sending IR codes @@ -656,13 +668,14 @@ If you see something like `Protocol=UNKNOWN Hash=0x13BD886C 35 bits received` as - If you have an **odd number of bits** received, your receiver circuit probably has problems. Maybe because the IR signal is too weak. - If you see timings like `+ 600,- 600 + 550,- 150 + 200,- 100 + 750,- 550` then one 450 µs space was split into two 150 and 100 µs spaces with a spike / error signal of 200 µs between. Maybe because of a defective receiver or a weak signal in conjunction with another light emitting source nearby. -- If you see timings like `+ 500,- 550 + 450,- 550 + 500,- 500 + 500,-1550`, then marks are generally shorter than spaces and therefore `MARK_EXCESS_MICROS` (specified in your ino file) should be **negative** to compensate for this at decoding. +- If you see 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). @@ -685,6 +698,11 @@ See also [DroneBot Workshop SimpleReceiver](https://dronebotworkshop.com/ir-remo 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. 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. +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 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 @@ -783,7 +801,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| -| `RAW_BUFFER_LENGTH` | 100 | Buffer size of raw input 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 100 requires 200 bytes, a value of 750 requires 1.5k bytes RAM. | +| `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. | | `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. | diff --git a/changelog.md b/changelog.md index 2891903f8..ec69d2d6e 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.4.0 +- Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]). +- Renamed decodedIRData.initialGap to decodedIRData.initialGapTicks. - sendNEC() and sendNEC2() now accepts 16 bit command to better map to NECext protocol found in IRDB databases. - ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. - Improved sensitivity and decoding of PULSE_DISTANCE + PULSE_WIDTH protocols. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index f828593b6..ed9e18cdf 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -36,14 +36,16 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 750. Default is 200. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 520 // Requires 1040 bytes RAM +#define RAW_BUFFER_LENGTH 360 +# else +#define RAW_BUFFER_LENGTH 750 +# endif + +# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # else -#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 400 // The decoder accepts mark or space durations up to 400 * 50 (MICROS_PER_TICK) = 20 milliseconds # endif #endif diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp index 3369306d2..7ac4cead0 100644 --- a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp +++ b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp @@ -1,3 +1,4 @@ +// LiquidCrystal_I2C.hpp // Based on the work by DFRobot /* * Extensions made by AJ 2023 @@ -7,6 +8,8 @@ * Added createChar() with PROGMEM input * Added fast timing */ +#ifndef _LIQUID_CRYSTAL_I2C_HPP +#define _LIQUID_CRYSTAL_I2C_HPP #include "Arduino.h" @@ -369,3 +372,4 @@ void LiquidCrystal_I2C::setContrast(uint8_t new_val) { } #pragma GCC diagnostic pop +#endif // _LIQUID_CRYSTAL_I2C_HPP diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index f2bac6552..8a315e9c7 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -36,11 +36,11 @@ * Otherwise you may get warnings like "type 'struct IRData' itself violates the C++ One Definition Rule" */ #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 750. Default is 200. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM +#define RAW_BUFFER_LENGTH 360 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index a2b580e10..3ec197ad8 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -33,11 +33,11 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 750. Default is 200. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM +#define RAW_BUFFER_LENGTH 360 +# else +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index fee20a3a4..a5bcae2b8 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -67,13 +67,11 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 750. Default is 200. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM +#define RAW_BUFFER_LENGTH 360 # else -#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 7fe00c342..ee4dc7519 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -72,13 +72,9 @@ // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 120 // 180 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 400 // 600 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; -# elif (defined(RAMEND) && RAMEND <= 0xAFF) || (defined(RAMSIZE) && RAMSIZE < 0xAFF) -#define RAW_BUFFER_LENGTH 500 // 750 is too much here, because we have additional uint8_t rawCode[RAW_BUFFER_LENGTH]; +// For air condition remotes it requires 750. Default is 200. +# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 88a897f2a..c0d9da014 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -57,13 +57,11 @@ #define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +// For air condition remotes it requires 750. Default is 200. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM +#define RAW_BUFFER_LENGTH 360 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM -# else -#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index d0a84e965..7a56be84f 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -73,12 +73,9 @@ // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 520 // Requires 1040 bytes RAM -#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds +// For air condition remotes it requires 750. Default is 200. +# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index e89ea39d5..8f58e31ca 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -36,13 +36,9 @@ #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM -# else -#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM +// For air condition remotes it requires 750. Default is 200. +# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 44ac4c759..36d79a6fd 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -62,7 +62,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. -//#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it requires 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 diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index 49a321f3d..17d84e08c 100644 --- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -37,7 +37,7 @@ * This must be done before the #include */ #define DECODE_HASH // special decoder for all protocols -#define RAW_BUFFER_LENGTH 600 // Requires 1200 bytes RAM. Especially useful for unknown and probably long protocols +#define RAW_BUFFER_LENGTH 1000 // Especially useful for unknown and probably long protocols //#define DEBUG // Activate this for lots of lovely debug output from the decoders. /* diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index 17218924d..a857203f2 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 180 // Requires 360 bytes RAM. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. +//#define RAW_BUFFER_LENGTH 750 // For air condition remotes it requires 750. Default is 200. #include diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 62c2b081d..cce8f42e4 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -38,9 +38,9 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. # if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 180 // Requires 360 bytes RAM +#define RAW_BUFFER_LENGTH 360 # elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 200 // 600 is too much here, because then variables are overwritten. 500 is OK without Pronto and 200 is OK with Pronto +#define RAW_BUFFER_LENGTH 400 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten. # endif #endif @@ -859,8 +859,8 @@ void loop() { /* * Force buffer overflow */ - Serial.println(F("Force buffer overflow by sending 280 marks and spaces")); - for (unsigned int i = 0; i < 140; ++i) { + 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. // 210 + 540 = 750 should be received as 5/10 or 4/11 if compensation by MARK_EXCESS_MICROS is optimal. IrSender.mark(210); // 8 pulses at 38 kHz diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 18db8dc08..7a2bebddd 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -121,12 +121,12 @@ struct IRData { /* * These 2 variables allow to call resume() directly after decode. - * After resume(), decodedIRData.rawDataPtr->rawbuf[0] and decodedIRData.rawDataPtr->rawlen are + * 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 initialGap; ///< contains the initial gap (rawbuf[0]) of the 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. }; diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 20c7c8eb0..e8c7a554c 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -218,7 +218,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap #if !defined(DISABLE_CODE_FOR_RECEIVER) if (aPrintRepeatGap) { aSerial->print(F(" gap=")); - aSerial->print((uint32_t) aIRDataPtr->initialGap * MICROS_PER_TICK); + aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK); aSerial->print(F("us")); } #else diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 55b1bc0a9..61f5d407a 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -164,7 +164,8 @@ void IRReceiveTimerInterruptHandler() { * Initialize all state machine variables */ irparams.OverflowFlag = false; - irparams.rawbuf[0] = irparams.TickCounterForISR; +// irparams.rawbuf[0] = irparams.TickCounterForISR; + irparams.initialGapTicks = irparams.TickCounterForISR; // Enabling 8 bit buffer since 4.4 irparams.rawlen = 1; irparams.StateForISR = IR_REC_STATE_MARK; } // otherwise stay in idle state @@ -218,6 +219,14 @@ void IRReceiveTimerInterruptHandler() { * Switch to IR_REC_STATE_STOP * Don't reset TickCounterForISR; keep counting width of next leading space */ + /* + * 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. + */ + IrReceiver.decodedIRData.initialGapTicks = irparams.initialGapTicks; + IrReceiver.decodedIRData.rawlen = irparams.rawlen; irparams.StateForISR = IR_REC_STATE_STOP; #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) /* @@ -480,16 +489,6 @@ void IRrecv::initDecodedIRData() { lastDecodedAddress = decodedIRData.address; } - - /* - * These 2 variables allow to call resume() directly after decode. - * After resume(), decodedIRData.rawDataPtr->rawbuf[0] and decodedIRData.rawDataPtr->rawlen are - * the first variables, which are overwritten by the next received frame. - * since 4.3.0. - */ - decodedIRData.initialGap = decodedIRData.rawDataPtr->rawbuf[0]; - decodedIRData.rawlen = decodedIRData.rawDataPtr->rawlen; - decodedIRData.protocol = UNKNOWN; decodedIRData.command = 0; decodedIRData.address = 0; @@ -1075,6 +1074,10 @@ bool IRrecv::decodeHash() { // Require at least 6 samples to prevent triggering on noise if (decodedIRData.rawlen < 6) { + IR_DEBUG_PRINT(F("HASH: ")); + IR_DEBUG_PRINT(F("Data length=")); + IR_DEBUG_PRINT(decodedIRData.rawlen); + IR_DEBUG_PRINTLN(F(" is less than 6")); return false; } for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) { @@ -1145,7 +1148,7 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants * 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.rawDataPtr->rawbuf[0] < aMaximumRepeatSpaceTicks + if (decodedIRData.initialGapTicks < aMaximumRepeatSpaceTicks #if defined(ENABLE_FULL_REPEAT_CHECK) && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 85 bytes program space */ #endif @@ -1269,10 +1272,10 @@ bool IRrecv::checkForRecordGapsMicros(Print *aSerial) { * is smaller than known value for protocols (Sony with around 24 ms) */ if (decodedIRData.protocol <= PULSE_DISTANCE - && decodedIRData.initialGap < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) { + && decodedIRData.initialGapTicks < (RECORD_GAP_MICROS_WARNING_THRESHOLD / MICROS_PER_TICK)) { aSerial->println(); aSerial->print(F("Space of ")); - aSerial->print(decodedIRData.initialGap * MICROS_PER_TICK); + aSerial->print(decodedIRData.initialGapTicks * MICROS_PER_TICK); aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of ")); aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD); aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc..")); @@ -1630,9 +1633,9 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI */ aSerial->print(F(" -")); if (aOutputMicrosecondsInsteadOfTicks) { - aSerial->println((uint32_t) decodedIRData.initialGap * MICROS_PER_TICK, DEC); + aSerial->println((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK, DEC); } else { - aSerial->println(decodedIRData.initialGap, DEC); + aSerial->println(decodedIRData.initialGapTicks, DEC); } // Newline is printed every 8. value, if tCounterForNewline % 8 == 0 @@ -1849,7 +1852,10 @@ bool IRrecv::decode_old(decode_results *aResults) { } // copy for usage by legacy programs - aResults->rawbuf = irparams.rawbuf; + aResults->rawbuf[0] = irparams.initialGapTicks; + for (int i = 1; i < RAW_BUFFER_LENGTH; ++i) { + aResults->rawbuf[i] = irparams.rawbuf[i]; // copy 8 bit array into a 16 bit array + } aResults->rawlen = irparams.rawlen; if (irparams.OverflowFlag) { // Copy overflow flag to decodedIRData.flags diff --git a/src/IRremote.hpp b/src/IRremote.hpp index a7af9fdc2..657f06878 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -107,7 +107,7 @@ # if !defined(EXCLUDE_EXOTIC_PROTOCOLS) // saves around 2000 bytes program memory #define DECODE_BOSEWAVE #define DECODE_LEGO_PF -#define DECODE_MAGIQUEST // It modifies the RAW_BUFFER_LENGTH from 100 to 112 +#define DECODE_MAGIQUEST #define DECODE_WHYNTER #define DECODE_FAST # endif @@ -157,19 +157,20 @@ * Keep in mind, that this is the delay between the end of the received command and the start of decoding. */ #if !defined(RECORD_GAP_MICROS) -// To change this value, you simply can add a line #define "RECORD_GAP_MICROS " in your ino file before the line "#include " +// To change this value, you simply can add a line #define "RECORD_GAP_MICROS " in your *.ino file before the line "#include " +// Maximum value for RECORD_GAP_MICROS, which fit into 8 bit buffer, using 50 us as tick, is 12750 #define RECORD_GAP_MICROS 8000 // RECS80 (https://www.mikrocontroller.net/articles/IRMP#RECS80) 1 bit space is 7500µs , NEC header space is 4500 #endif /** * Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value. */ #if !defined(RECORD_GAP_MICROS_WARNING_THRESHOLD) -// To change this value, you simply can add a line #define "RECORD_GAP_MICROS_WARNING_THRESHOLD " in your ino file before the line "#include " +// To change this value, you simply can add a line #define "RECORD_GAP_MICROS_WARNING_THRESHOLD " in your *.ino file before the line "#include " #define RECORD_GAP_MICROS_WARNING_THRESHOLD 15000 #endif /** Minimum gap between IR transmissions, in MICROS_PER_TICK */ -#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 100 +#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) /* * Activate this line if your receiver has an external output driver transistor / "inverted" output diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 4f95900ae..fc204e0c1 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -64,20 +64,21 @@ #define USE_DEFAULT_FEEDBACK_LED_PIN 0 /** - * The length of the buffer where the IR timing data is stored before decoding - * 100 is sufficient for most standard protocols, but air conditioners often send a longer protocol data stream + * 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. + * 48 bit protocols are PANASONIC, KASEIKYO, SAMSUNG48, RC6. + * 32 bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28) requires a buffer length of 68. + * 16 bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) requires a buffer length of 36. + * MAGIQUEST requires a buffer length of 112. + * Air conditioners often send a longer protocol data stream up to 750 bits. */ #if !defined(RAW_BUFFER_LENGTH) # if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) // for RAMsize <= 2k -# if defined(DECODE_MAGIQUEST) -#define RAW_BUFFER_LENGTH 112 // MagiQuest requires 224 bytes. -# else -#define RAW_BUFFER_LENGTH 100 ///< Length of raw duration buffer. 100 -> 200 bytes. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit. -# endif +#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 // For undefined or bigger RAMsize -#define RAW_BUFFER_LENGTH 750 // Requires 1500 bytes RAM. The value for air condition remotes. +#define RAW_BUFFER_LENGTH 750 // The value for air condition remotes. # endif #endif #if RAW_BUFFER_LENGTH % 2 == 1 @@ -89,6 +90,29 @@ typedef uint_fast8_t IRRawlenType; #else typedef unsigned int IRRawlenType; #endif + +/* + * Use 8 bit buffer for IR timing in 50 ticks units. + * It is save to use 8 bit if RECORD_GAP_TICKS < 256, since any value greater 255 is interpreted as frame gap of 12750 us. + * The default for frame gap is currently 8000! + * But if we assume that for most protocols the frame gap is way greater than the biggest mark or space duration, + * 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 +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. +#endif + +#if (__INT_WIDTH__ < 32) +typedef uint32_t IRRawDataType; +#define BITS_IN_RAW_DATA_TYPE 32 +#else +typedef uint64_t IRRawDataType; +#define BITS_IN_RAW_DATA_TYPE 64 +#endif + /**************************************************** * Declarations for the receiver Interrupt Service Routine ****************************************************/ @@ -103,7 +127,7 @@ typedef unsigned int IRRawlenType; * Only StateForISR needs to be volatile. All the other fields are not written by ISR after data available and before start/resume. */ struct irparams_struct { - // The fields are ordered to reduce memory over caused by struct-padding + // The fields are ordered to reduce memory overflow caused by struct-padding volatile uint8_t StateForISR; ///< State Machine state uint_fast8_t IRReceivePin; ///< Pin connected to IR data from detector #if defined(__AVR__) @@ -115,17 +139,11 @@ struct irparams_struct { void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP #endif bool OverflowFlag; ///< Raw buffer OverflowFlag occurred - IRRawlenType rawlen; ///< counter of entries in rawbuf - uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command + IRRawlenType rawlen; ///< counter of entries in rawbuf + uint16_t initialGapTicks; ///< Tick counts of the length of the gap between previous and current IR frame. Pre 4.4: rawbuf[0]. + 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. }; -#if (__INT_WIDTH__ < 32) -typedef uint32_t IRRawDataType; -#define BITS_IN_RAW_DATA_TYPE 32 -#else -typedef uint64_t IRRawDataType; -#define BITS_IN_RAW_DATA_TYPE 64 -#endif #include "IRProtocol.h" /* @@ -171,7 +189,7 @@ 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 + uint16_t *rawbuf; // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks uint_fast8_t rawlen; // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long }; diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index d54f6d500..628a5792e 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -97,7 +97,7 @@ #if defined(DECODE_BEO) # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) # if RECORD_GAP_MICROS > 15000 -#warning If defined ENABLE_BEO_WITHOUT_FRAME_GAP, RECORD_GAP_MICROS must be set to <= 15000 by "#define RECORD_GAP_MICROS 13000" +#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 @@ -310,7 +310,7 @@ bool IRrecv::decodeBangOlufsen() { uint8_t tBitNumber = 0; BEO_TRACE_PRINT(F("Pre gap: ")); - BEO_TRACE_PRINT(decodedIRData.initialGap * 50); + BEO_TRACE_PRINT(decodedIRData.initialGapTicks * 50); BEO_TRACE_PRINT(F(" raw len: ")); BEO_TRACE_PRINTLN(decodedIRData.rawlen); @@ -332,7 +332,7 @@ bool IRrecv::decodeBangOlufsen() { /* * Check if leading gap is trailing bit of first frame */ - if (!matchSpace(decodedIRData.initialGap, BEO_PULSE_LENGTH_START_BIT)) { + 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 return false; // no B&O protocol diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index 60cd65a9f..f22141145 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -189,7 +189,7 @@ bool IRrecv::decodeDenon() { decodedIRData.command &= 0xFF; // Check for (auto) repeat - if (decodedIRData.initialGap < ((DENON_AUTO_REPEAT_DISTANCE + (DENON_AUTO_REPEAT_DISTANCE / 4)) / MICROS_PER_TICK)) { + 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; diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 5744dc679..aa2d4ed24 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -333,7 +333,7 @@ bool IRrecv::decodeDistanceWidth() { Serial.print(F(", ")); Serial.println(tSpaceTicksShort * MICROS_PER_TICK); #endif -#if RAW_BUFFER_LENGTH <= 508 +#if RAW_BUFFER_LENGTH <= (512 -4) uint_fast8_t tNumberOfBits; #else uint16_t tNumberOfBits; diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index 0a6543a10..f9ea167cd 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -1,7 +1,8 @@ /* * ir_FAST.hpp * - * Contains functions for receiving and sending FAST IR protocol with 8 bit command + * Contains functions for receiving and sending FAST IR protocol + * with no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index c827859f8..614cc00c7 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -135,7 +135,7 @@ bool IRrecv::decodeJVC() { * Check for repeat * Check leading space and first and last mark length */ - if (decodedIRData.initialGap < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK)) + 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)) { /* diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 9f99ebf32..fed25bccf 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -187,7 +187,7 @@ bool IRrecv::decodeLegoPowerFunctions() { /* * Check for autorepeat (should happen 4 times for one press) */ - if (decodedIRData.initialGap < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) { + if (decodedIRData.initialGapTicks < (LEGO_AUTO_REPEAT_PERIOD_MAX / MICROS_PER_TICK)) { decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT; } decodedIRData.address = tToggleEscapeChannel; diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 3b67e80ad..06bc15e70 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -232,7 +232,7 @@ static void dumpDuration(Print *aSerial, uint32_t duration, uint16_t timebase) { /* * Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding! */ -static void compensateAndDumpSequence(Print *aSerial, const volatile uint16_t *data, size_t length, uint16_t timebase) { +static void compensateAndDumpSequence(Print *aSerial, const volatile IRRawbufType *data, size_t length, uint16_t timebase) { for (size_t i = 0; i < length; i++) { uint32_t tDuration = data[i] * MICROS_PER_TICK; if (i & 1) { @@ -297,7 +297,7 @@ static size_t dumpDuration(String *aString, uint32_t duration, uint16_t timebase return dumpNumber(aString, (duration + timebase / 2) / timebase); } -static size_t compensateAndDumpSequence(String *aString, const volatile uint16_t *data, size_t length, uint16_t timebase) { +static size_t compensateAndDumpSequence(String *aString, const volatile IRRawbufType *data, size_t length, uint16_t timebase) { size_t size = 0; diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 9c161242a..2cc8dd43f 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -85,7 +85,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 #define RC5_UNIT 889 // 32 periods of 36 kHz (888.8888) -#define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7. Divided by 2 to handle the bit sequence of 01010101 which gives one mark and space for each 2 bits +#define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7 - Divided by 2 to handle the bit sequence of 01010101 which gives one mark and space for each 2 bits #define RC5_DURATION (15L * RC5_UNIT) // 13335 #define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792 From 6ae07f8a79478fc1a0461ebea2011b30a46976b8 Mon Sep 17 00:00:00 2001 From: akellai <4593276+akellai@users.noreply.github.com> Date: Sun, 14 Jul 2024 10:54:22 +0200 Subject: [PATCH 054/133] support for esp32 3.0 (#1245) * slight changes for esp32 board ver 3.0.x to work * esp32 core 3 - send is fixed --- src/private/IRTimer.hpp | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 0b129eb56..3868598f9 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1434,20 +1434,18 @@ void timerConfigForReceive() { * so it is recommended to always define SEND_PWM_BY_TIMER **********************************************************/ #elif defined(ESP32) -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) -#error This library does not work with ESP32 core 3.x. Please use ESP 2.0.17 core. You are kindly invited to port and document the code to 3.x, to fix this problem! -# endif - // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) +# if !defined(SEND_LEDC_CHANNEL) #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif void timerEnableReceiveInterrupt() { - timerAlarmEnable(s50usTimer); + #if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically + timerAlarmEnable(s50usTimer); + #endif } # if !defined(ESP_ARDUINO_VERSION) @@ -1466,7 +1464,11 @@ void timerDisableReceiveInterrupt() { # else void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { - timerAlarmDisable(s50usTimer); + #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) + timerEnd(s50usTimer); + #else + timerAlarmDisable(s50usTimer); + #endif } } # endif @@ -1482,9 +1484,16 @@ void timerConfigForReceive() { // simply call the readable API versions :) // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if(s50usTimer == NULL) { - s50usTimer = timerBegin(1, 80, true); - timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( - timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true); + + #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) + s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec + timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); + timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever + #else + s50usTimer = timerBegin(1, 80, true); + timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( + timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true); + #endif } // every 50 us, autoreload = true } @@ -1499,14 +1508,22 @@ void enableSendPWMByTimer() { # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution # else +# if defined(IR_SEND_PIN) + ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API +# else ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API +# endif # endif } void disableSendPWMByTimer() { # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) ledcWrite(SEND_LEDC_CHANNEL, 0); # else +# if defined(IR_SEND_PIN) + ledcWrite(IR_SEND_PIN, 0); // New API +# else ledcWrite(IrSender.sendPin, 0); // New API +# endif # endif } From 0eda1ee1fbb8fb99a4d78b0a185edee717e51e38 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 14 Jul 2024 13:10:21 +0200 Subject: [PATCH 055/133] Documentation --- Contributors.md | 1 + README.md | 2 +- changelog.md | 2 ++ src/IRReceive.hpp | 6 ++++ src/private/IRTimer.hpp | 69 +++++++++++++++++++++++------------------ 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/Contributors.md b/Contributors.md index 349ccec14..40c040464 100644 --- a/Contributors.md +++ b/Contributors.md @@ -31,5 +31,6 @@ 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. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/README.md b/README.md index 0ee428a6a..4dcaaedbd 100644 --- a/README.md +++ b/README.md @@ -878,7 +878,7 @@ ATtiny boards are only tested with [ATTinyCore](https://github.com/SpenceKonde/A - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD21 (Zero, MKR*, **but not SAMD51 and not DUE, the latter is SAM architecture**) - ESP8266 -- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) **not for ESP32 core version > 3.0.0** +- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) - Sparkfun Pro Micro - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 diff --git a/changelog.md b/changelog.md index ec69d2d6e..af477fc2c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,8 @@ # Changelog The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.4.1 +- Support for ESP 3.0 by akellai. # 4.4.0 - Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]). diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 61f5d407a..68f49f2db 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -116,6 +116,8 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { * => Minimal CPU frequency is 4 MHz * **********************************************************************************************************************/ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wvolatile" #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif @@ -389,6 +391,8 @@ void IRrecv::enableIRIn() { /** * Configures the timer and the state machine for IR reception. + * 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. * @param aMicrosecondsToAddToGapCounter To compensate for the amount of microseconds the timer was stopped / disabled. */ @@ -416,6 +420,8 @@ void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCou void IRrecv::addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter) { irparams.TickCounterForISR += aMicrosecondsToAddToInternalTickCounter / MICROS_PER_TICK; } +#pragma GCC diagnostic push + /** * Restarts receiver after send. Is a NOP if sending does not require a timer. */ diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 3868598f9..c8bf924ca 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1434,6 +1434,13 @@ void timerConfigForReceive() { * so it is recommended to always define SEND_PWM_BY_TIMER **********************************************************/ #elif defined(ESP32) +# if !defined(ESP_ARDUINO_VERSION) +#define ESP_ARDUINO_VERSION 0 +# endif +# if !defined(ESP_ARDUINO_VERSION_VAL) +#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202 +# endif + // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() @@ -1443,17 +1450,14 @@ hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() # endif void timerEnableReceiveInterrupt() { - #if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically timerAlarmEnable(s50usTimer); - #endif +# endif } -# if !defined(ESP_ARDUINO_VERSION) -#define ESP_ARDUINO_VERSION 0 -# endif -# if !defined(ESP_ARDUINO_VERSION_VAL) -#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202 -# endif +/* + * Special support for ESP core < 202 + */ # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { @@ -1464,11 +1468,11 @@ void timerDisableReceiveInterrupt() { # else void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { - #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) timerEnd(s50usTimer); - #else +# else timerAlarmDisable(s50usTimer); - #endif +# endif } } # endif @@ -1485,15 +1489,15 @@ void timerConfigForReceive() { // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if(s50usTimer == NULL) { - #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) + s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); - timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever - #else + timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever +# else s50usTimer = timerBegin(1, 80, true); timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true); - #endif +# endif } // every 50 us, autoreload = true } @@ -1505,25 +1509,27 @@ uint8_t sLastSendPin = 0; // To detach before attach, if already attached # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution -# else +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API # else ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API # endif +# else + // ESP version < 3.0 + ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution # endif } void disableSendPWMByTimer() { -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcWrite(SEND_LEDC_CHANNEL, 0); -# else +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) ledcWrite(IR_SEND_PIN, 0); // New API # else ledcWrite(IrSender.sendPin, 0); // New API # endif +# else + // ESP version < 3.0 + ledcWrite(SEND_LEDC_CHANNEL, 0); # endif } @@ -1532,25 +1538,26 @@ void disableSendPWMByTimer() { * ledcWrite since ESP 2.0.2 does not work if pin mode is set. */ void timerConfigForSend(uint16_t aFrequencyKHz) { -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) - ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // New API # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ - ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194 + ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel + ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // New API sLastSendPin = IrSender.sendPin; # endif -# else // New API here +# else + // ESP version < 3.0 + ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution # if defined(IR_SEND_PIN) - ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // New API + ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ - ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 + ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // New API + ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel sLastSendPin = IrSender.sendPin; # endif # endif From 13ca5ce7acf1f20bc56ac93bf0ba37f702f328da Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 21 Jul 2024 13:04:30 +0200 Subject: [PATCH 056/133] restartTimer() now uses variable sMicrosAtLastStopTimer to keep track of uncounted ticks between stopTimer() and restartTimer() --- README.md | 25 ++++++---- changelog.md | 3 ++ .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 10 ++-- examples/ReceiveDemo/ReceiveDemo.ino | 11 ++--- .../ReceiveOneAndSendMultiple.ino | 2 +- examples/TinyReceiver/TinyReceiver.ino | 11 ++++- src/IRReceive.hpp | 46 +++++++++++-------- src/IRremoteInt.h | 12 ++--- src/TinyIR.h | 10 ++-- src/TinyIRReceiver.hpp | 14 +++++- src/private/IRTimer.hpp | 38 +++++++-------- 11 files changed, 109 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 4dcaaedbd..13260d97e 100644 --- a/README.md +++ b/README.md @@ -518,10 +518,10 @@ void setup() { } void loop() { - if (TinyIRReceiverData.justWritten) { - TinyIRReceiverData.justWritten = false; + if (TinyReceiverDecode()) { printTinyReceiverResultMinimal(&Serial); } + // No resume() required :-) } ``` @@ -953,8 +953,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,14 +974,20 @@ 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/21b5747a58e9d47c9e3f1beb056d58c875a92b47/examples/ReceiveDemo/ReceiveDemo.ino#L159-L169), 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.
diff --git a/changelog.md b/changelog.md index af477fc2c..5234a9750 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,9 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.4.1 - Support for ESP 3.0 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(). # 4.4.0 - Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]). diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index ed9e18cdf..c70463de2 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -240,7 +240,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 +259,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 +285,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) diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 7a56be84f..358c31188 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -181,8 +181,7 @@ 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) { @@ -256,13 +255,13 @@ void loop() { */ 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(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. + 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 } @@ -286,7 +285,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/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index 28f5c2524..a4a584f06 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -222,7 +222,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/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index bad39fea2..d8c440d44 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -106,14 +106,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 +122,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/src/IRReceive.hpp b/src/IRReceive.hpp index 68f49f2db..b2e933e2a 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -62,6 +62,7 @@ IRrecv IrReceiver; * The control structure 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. @@ -116,9 +117,9 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { * => Minimal CPU frequency is 4 MHz * **********************************************************************************************************************/ +#if defined(ESP8266) || defined(ESP32) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvolatile" -#if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif void IRReceiveTimerInterruptHandler() { @@ -377,6 +378,10 @@ 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); @@ -394,33 +399,30 @@ void IRrecv::enableIRIn() { * 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 } void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) { irparams.TickCounterForISR += aTicksToAddToGapCounter; - restartTimer(); -} - -void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) { - irparams.TickCounterForISR += aTicksToAddToInternalTickCounter; -} - -void IRrecv::addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter) { - irparams.TickCounterForISR += aMicrosecondsToAddToInternalTickCounter / MICROS_PER_TICK; -} + 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 /** * Restarts receiver after send. Is a NOP if sending does not require a timer. @@ -438,8 +440,12 @@ void IRrecv::stop() { timerDisableReceiveInterrupt(); } +/* + * Stores microseconds of stop, to adjust TickCounterForISR in restartTimer() + */ void IRrecv::stopTimer() { timerDisableReceiveInterrupt(); + sMicrosAtLastStopTimer = micros(); } /** * Alias for stop(). diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index fc204e0c1..468299056 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -113,9 +113,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. @@ -144,6 +144,8 @@ 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. }; +extern unsigned long sMicrosAtLastStopTimer; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer() + #include "IRProtocol.h" /* @@ -213,17 +215,13 @@ class IRrecv { */ 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 diff --git a/src/TinyIR.h b/src/TinyIR.h index 4f89fa2c5..c01a67ab9 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -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 @@ -243,7 +243,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 +252,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); @@ -263,6 +264,9 @@ 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 = 0, bool aSendNEC2Repeats = false); /* + * 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..39b3414e3 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -84,7 +84,6 @@ //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. - #include "TinyIR.h" // If not defined, it defines IR_RECEIVE_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT #include "digitalWriteFast.h" @@ -384,7 +383,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 +425,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 diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index c8bf924ca..9e395a73d 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1450,15 +1450,17 @@ hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() # endif void timerEnableReceiveInterrupt() { -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically - timerAlarmEnable(s50usTimer); +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically + timerStart(s50usTimer); +# else + timerAlarmEnable(s50usTimer); # endif } +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) /* * Special support for ESP core < 202 */ -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { timerDetachInterrupt(s50usTimer); @@ -1466,12 +1468,13 @@ void timerDisableReceiveInterrupt() { } } # else + void timerDisableReceiveInterrupt() { if (s50usTimer != NULL) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - timerEnd(s50usTimer); + timerStop(s50usTimer); # else - timerAlarmDisable(s50usTimer); + timerAlarmDisable(s50usTimer); # endif } } @@ -1488,15 +1491,14 @@ void timerConfigForReceive() { // simply call the readable API versions :) // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if(s50usTimer == NULL) { - # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec - timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); - timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever + s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec + timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); + timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever # else - s50usTimer = timerBegin(1, 80, true); - timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( - timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true); + s50usTimer = timerBegin(1, 80, true); + timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( + timerAlarmWrite(s50usTimer, MICROS_PER_TICK, true); # endif } // every 50 us, autoreload = true @@ -1511,9 +1513,9 @@ uint8_t sLastSendPin = 0; // To detach before attach, if already attached void enableSendPWMByTimer() { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API + ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API # else - ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // New API + ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API # endif # else // ESP version < 3.0 @@ -1523,9 +1525,9 @@ void enableSendPWMByTimer() { void disableSendPWMByTimer() { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcWrite(IR_SEND_PIN, 0); // New API + ledcWrite(IR_SEND_PIN, 0); // 3.x API # else - ledcWrite(IrSender.sendPin, 0); // New API + ledcWrite(IrSender.sendPin, 0); // 3.x API # endif # else // ESP version < 3.0 @@ -1540,12 +1542,12 @@ void disableSendPWMByTimer() { void timerConfigForSend(uint16_t aFrequencyKHz) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // New API + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // 3.x API # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // New API + ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // 3.x API sLastSendPin = IrSender.sendPin; # endif # else From c2b95a3bb148d7c1ca0f9937e16db120da7c6c4d Mon Sep 17 00:00:00 2001 From: luiwagner <144788879+luiwagner@users.noreply.github.com> Date: Sat, 3 Aug 2024 19:54:07 +0200 Subject: [PATCH 057/133] Edited 2.x and 4.x Example (#1254) * Update README.md Added Serial.begin(115200) to the old 2.x and new 4.x program * Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 13260d97e..8280c069d 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,7 @@ decode_results results; void setup() { ... + Serial.begin(115200); // Establish serial communication irrecv.enableIRIn(); // Start the receiver } @@ -203,6 +204,7 @@ void loop() { void setup() { ... + Serial.begin(115200); // // Establish serial communication IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver } From 9a4ea5911222b10555914ac63b0f690d52600233 Mon Sep 17 00:00:00 2001 From: Craig Leres Date: Sat, 3 Aug 2024 11:00:56 -0700 Subject: [PATCH 058/133] Add some missing F() invocations. (#1253) Use ... println() instead of println("") to get a blank newline. --- src/IRReceive.hpp | 10 +++++----- src/IRSend.hpp | 2 +- src/ir_Pronto.hpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index b2e933e2a..44bbbae8f 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1542,11 +1542,11 @@ void IRrecv::printIRSendUsage(Print *aSerial) { /* * 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); @@ -1707,7 +1707,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI } aSerial->println(); - aSerial->print("Sum: "); + aSerial->print(F("Sum: ")); if (aOutputMicrosecondsInsteadOfTicks) { aSerial->println((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); } else { @@ -1770,7 +1770,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr printIRResultShort(aSerial); // Newline - aSerial->println(""); + aSerial->println(); } /** diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 470c64790..5669b1dea 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -926,7 +926,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas tLastBitValue = 0; } } - IR_TRACE_PRINTLN(F("")); + IR_TRACE_PRINTLN(); } /** diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 06bc15e70..b7b31d271 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -263,7 +263,7 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFreque dumpNumber(aSerial, 0); uint16_t timebase = toTimebase(aFrequencyHertz); compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space - aSerial->println("\";"); + aSerial->println(F("\";")); } /* From 7a115e8de2895e0de7d086c9aa5e33986f16d1cc Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 12 Aug 2024 11:28:24 +0200 Subject: [PATCH 059/133] Closes #1255 --- src/IRReceive.hpp | 14 ++++++++++++-- src/IRremoteInt.h | 4 ++-- src/digitalWriteFast.h | 4 ++++ src/ir_Lego.hpp | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 44bbbae8f..ec7963d40 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -227,10 +227,12 @@ void IRReceiveTimerInterruptHandler() { * 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. + * 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) @@ -419,7 +421,7 @@ void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) { #ifdef _IR_MEASURE_TIMING pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif - } +} #if defined(ESP8266) || defined(ESP32) #pragma GCC diagnostic push #endif @@ -540,6 +542,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) { diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 468299056..716d4ebc2 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -203,8 +203,8 @@ class IRrecv { public: IRrecv(); - IRrecv(uint_fast8_t aReceivePin); - IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin); + 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.."))); void setReceivePin(uint_fast8_t aReceivePinNumber); #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) void registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)); diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index 1bb8eb507..043ae7150 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -29,6 +29,10 @@ #include // declarations for the fallback to digitalWrite(), digitalRead() etc. +#if defined(MEGATINYCORE) +#error Do not use "#include digitalWriteFast.h" because megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast(). +#endif + // --- Arduino Mega and ATmega128x/256x based boards --- #if (defined(ARDUINO_AVR_MEGA) || \ defined(ARDUINO_AVR_MEGA1280) || \ diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index fed25bccf..1885f3bfa 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -132,7 +132,7 @@ bool IRrecv::decodeLegoPowerFunctions() { } // 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); From 39136b65a295f992c2c25f8b251ba839ba93ef3d Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 13 Aug 2024 17:14:12 +0200 Subject: [PATCH 060/133] Bumped version to 4.4.1 --- .../SimpleReceiverForHashCodes.ino | 12 ++++++------ library.json | 2 +- library.properties | 2 +- src/IRVersion.h | 4 ++-- src/private/IRTimer.hpp | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index 17d84e08c..1766e7c3f 100644 --- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -68,22 +68,22 @@ 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) { + auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs + if (tDecodedRawData == 0x4F7BE2FB) { // do something - } else if (IrReceiver.decodedIRData.decodedRawData == 0x97483BFB) { + } else if (tDecodedRawData == 0x97483BFB) { // do something else } } diff --git a/library.json b/library.json index eae4a2593..cda754b22 100644 --- a/library.json +++ b/library.json @@ -7,7 +7,7 @@ "type": "git", "url": "https://github.com/Arduino-IRremote/Arduino-IRremote.git" }, - "version": "4.4.0", + "version": "4.4.1", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "authors" : diff --git a/library.properties b/library.properties index e235679e6..e42b826e8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.4.0 +version=4.4.1 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRVersion.h b/src/IRVersion.h index 668bb9a14..d4dd23f3b 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.4.0" +#define VERSION_IRREMOTE "4.4.1" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 4 -#define VERSION_IRREMOTE_PATCH 0 +#define VERSION_IRREMOTE_PATCH 1 /* * Macro to convert 3 version parts into an integer diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 9e395a73d..acb1b97c4 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1492,7 +1492,7 @@ void timerConfigForReceive() { // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if(s50usTimer == NULL) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - s50usTimer = timerBegin(1000000); // only 1 parameter is required. 1 MHz corresponds to 1 uSec + s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever # else From b737e8323a3b3e0fe8209cbfb8af566fb0c5e251 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 22 Aug 2024 01:18:41 +0200 Subject: [PATCH 061/133] ESP32 timer massaging --- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 11 +++++- examples/ControlRelay/PinDefinitionsAndMore.h | 11 +++++- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- examples/MicroGirs/PinDefinitionsAndMore.h | 11 +++++- .../ReceiveAndSend/PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- examples/ReceiveDemo/PinDefinitionsAndMore.h | 11 +++++- examples/ReceiveDemo/ReceiveDemo.ino | 19 ++++++---- examples/ReceiveDump/PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- .../SendAndReceive/PinDefinitionsAndMore.h | 11 +++++- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 11 +++++- examples/SendDemo/PinDefinitionsAndMore.h | 11 +++++- examples/SendDemo/SendDemo.ino | 9 +++++ .../PinDefinitionsAndMore.h | 11 +++++- .../SendProntoDemo/PinDefinitionsAndMore.h | 11 +++++- examples/SendRawDemo/PinDefinitionsAndMore.h | 11 +++++- .../SimpleReceiver/PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- .../PinDefinitionsAndMore.h | 11 +++++- examples/SimpleSender/PinDefinitionsAndMore.h | 11 +++++- examples/TinyReceiver/PinDefinitionsAndMore.h | 11 +++++- examples/TinySender/PinDefinitionsAndMore.h | 11 +++++- examples/UnitTest/PinDefinitionsAndMore.h | 11 +++++- examples/UnitTest/UnitTest.ino | 37 +++++++++++++++---- src/IRFeedbackLED.hpp | 14 +++---- src/IRReceive.hpp | 2 +- src/IRSend.hpp | 6 +-- src/private/IRTimer.hpp | 15 +++++--- 31 files changed, 287 insertions(+), 79 deletions(-) diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 358c31188..48edd73a4 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -135,18 +135,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 + #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 ")); + Serial.print(F("If you connect debug pin ")); # if defined(APPLICATION_PIN_STRING) - Serial.print(APPLICATION_PIN_STRING); + Serial.print(APPLICATION_PIN_STRING); # else - Serial.print(DEBUG_BUTTON_PIN); + Serial.print(DEBUG_BUTTON_PIN); # endif - Serial.print(F(" to ground, ")); - } - Serial.println(F("raw data is always printed")); + Serial.println(F(" to ground, raw data is always printed and tone is disabled")); // infos for receive Serial.print(RECORD_GAP_MICROS); diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index c644f3e4c..5a738da30 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -93,6 +93,15 @@ void setup() { Serial.print(IrSender.periodTimeMicros); Serial.println(F(" us")); #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 + } /* diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 37d57d93a..14573c786 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -42,7 +42,7 @@ * SAMD21 3 4 5 * 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 @@ -172,7 +172,14 @@ #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... diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index cce8f42e4..aac41eb2c 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -48,7 +48,9 @@ //#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition +#if FLASHEND <= 0x7FFF // For 32k flash or less, like ATmega328 #define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory +#endif // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. @@ -142,6 +144,14 @@ 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))); @@ -390,10 +400,13 @@ void loop() { IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); + /* + * Complete NEC frames as repeats to force decoding as NEC2 are tested here + */ for (int8_t i = 0; i < sRepeats; i++) { 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); checkReceive(sAddress & 0xFF, sCommand); @@ -492,8 +505,8 @@ void loop() { 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 +520,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 @@ -522,7 +536,7 @@ void loop() { 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); @@ -560,7 +574,8 @@ void loop() { 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); + 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); @@ -881,6 +896,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/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 97611b083..ff83b762b 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -109,16 +109,16 @@ 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 + digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED on #else digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED on #endif #if defined(LED_BUILTIN) // use fast macros here - } else { + } 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 } @@ -130,11 +130,11 @@ void setFeedbackLED(bool aSwitchLedOn) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED off #endif #if defined(LED_BUILTIN) - } else { + } 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 } diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index ec7963d40..1fb0ec6ce 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -257,7 +257,7 @@ void IRReceiveTimerInterruptHandler() { } #if !defined(NO_LED_FEEDBACK_CODE) - if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_RECEIVE) { + if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_RECEIVE) { setFeedbackLED(tIRInputLevel == INPUT_MARK); } #endif diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 5669b1dea..66813366d 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -1040,7 +1040,7 @@ void IRsend::mark(uint16_t aMarkMicros) { */ if (!FeedbackLedIsActive) { FeedbackLedIsActive = true; - if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { + if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(true); } } @@ -1080,7 +1080,7 @@ void IRsend::mark(uint16_t aMarkMicros) { // 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) { + if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } } @@ -1135,7 +1135,7 @@ void IRsend::IRLedOff() { #endif #if !defined(NO_LED_FEEDBACK_CODE) - if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { + if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } #endif diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index acb1b97c4..a670f55d5 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1450,7 +1450,7 @@ hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() # endif void timerEnableReceiveInterrupt() { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically +# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) timerStart(s50usTimer); # else timerAlarmEnable(s50usTimer); @@ -1492,7 +1492,8 @@ void timerConfigForReceive() { // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if(s50usTimer == NULL) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec + s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. + timerStop(s50usTimer); // Stop it here, to avoid "error E (3447) gptimer: gptimer_start(348): timer is not enabled yet" at timerEnableReceiveInterrupt() timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever # else @@ -1505,9 +1506,8 @@ void timerConfigForReceive() { } # endif -# if !defined(IR_SEND_PIN) -uint8_t sLastSendPin = 0; // To detach before attach, if already attached -# endif + +uint8_t sLastSendPin = 0; // Avoid multiple attach() or if pin changes, detach before attach # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { @@ -1542,7 +1542,10 @@ void disableSendPWMByTimer() { void timerConfigForSend(uint16_t aFrequencyKHz) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // 3.x API + if(sLastSendPin == 0){ + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // 3.x API + sLastSendPin = IR_SEND_PIN; + } # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 From cee69fa291447e33519d459352f572c6aa659cc7 Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 26 Aug 2024 12:31:59 +0200 Subject: [PATCH 062/133] Documentation --- README.md | 9 +++++++++ pictures/IR_RobotCar.jpg | Bin 0 -> 163679 bytes 2 files changed, 9 insertions(+) create mode 100644 pictures/IR_RobotCar.jpg diff --git a/README.md b/README.md index 8280c069d..57c58c96b 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) @@ -787,6 +788,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.
+![IR_RobotCar](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_RobotCar.jpg) +
# Issues and discussions diff --git a/pictures/IR_RobotCar.jpg b/pictures/IR_RobotCar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6258d0136b3d661ac722dbc3cc0534e29fe960d9 GIT binary patch literal 163679 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
&Wc=^;n|cT&QXk&Y8ixs$G~ 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 z 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

V7~EogUwX?VyE1#;enATz2c8^=mfE3|LXlal1Ea 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 Date: Wed, 28 Aug 2024 20:54:10 +0200 Subject: [PATCH 063/133] Support for RC6A --- README.md | 137 ++++++++++++++------------- changelog.md | 2 + examples/ReceiveDemo/ReceiveDemo.ino | 8 +- examples/ReceiveDump/ReceiveDump.ino | 2 +- examples/SendDemo/SendDemo.ino | 5 + examples/UnitTest/UnitTest.ino | 20 +++- examples/UnitTest/UnitTest.log | 15 +++ examples/UnitTest/UnitTest_64bit.log | 15 +++ src/IRProtocol.h | 3 + src/IRProtocol.hpp | 3 +- src/IRReceive.hpp | 4 +- src/IRremoteInt.h | 3 +- src/ir_RC5_RC6.hpp | 77 +++++++++++++-- src/private/IRTimer.hpp | 22 +++-- 14 files changed, 216 insertions(+), 100 deletions(-) diff --git a/README.md b/README.md index 57c58c96b..1694220ef 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,13 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [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](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#other-libraries) + * [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 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) @@ -63,11 +68,6 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) @@ -351,6 +351,9 @@ Often the address is also constant, which further reduces memory requirements. # IRReceiver pinouts ![IRReceiver Pinout](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IRReceiverPinout.jpg) +[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()) {}`
@@ -435,12 +438,6 @@ 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. @@ -454,6 +451,68 @@ 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 +#### 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. @@ -638,60 +697,6 @@ 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.
diff --git a/changelog.md b/changelog.md index 5234a9750..50d3d8747 100644 --- a/changelog.md +++ b/changelog.md @@ -1,11 +1,13 @@ # Changelog The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master + # 4.4.1 - Support for ESP 3.0 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]). diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 48edd73a4..99468db8d 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -66,16 +66,13 @@ // !!! 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! -#endif // etc. see IRremote.hpp // #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 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 @@ -88,6 +85,9 @@ // 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. +#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. diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 8f58e31ca..d0451baa2 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -38,7 +38,7 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 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 diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 5a738da30..362326401 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -360,6 +360,11 @@ void loop() { IrSender.sendRC6(sAddress, sCommand, sRepeats, true); 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); + 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 MagiQuest")); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index aac41eb2c..af464aa51 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -90,10 +90,11 @@ #endif #define DECODE_BOSEWAVE -//#define DECODE_LEGO_PF #define DECODE_MAGIQUEST -//#define DECODE_WHYNTER #define DECODE_FAST + +//#define DECODE_WHYNTER +//#define DECODE_LEGO_PF #endif //#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below @@ -481,11 +482,13 @@ void loop() { delay(DELAY_AFTER_SEND); # endif +# if __INT_WIDTH__ < 32 + IRRawDataType tRawData[4] = { 0xB02002, 0xA010, 0x0, 0x0 }; // LSB of tRawData[0] is sent first +# endif # if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); 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 checkReceive(0x0B, 0x10); # else @@ -606,7 +609,7 @@ 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")); 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); @@ -760,11 +763,18 @@ void loop() { #if defined(DECODE_RC6) Serial.println(F("Send RC6")); - // RC6 check does not work stable without the flush Serial.flush(); + sLastSendToggleValue = sAddress & 0x01; // to modify toggling at each loop + IrSender.sendRC6(sAddress & 0xFF, sCommand, 0, 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, 0, 0x2711, true); + checkReceive(sAddress & 0xFF, sCommand); + delay(DELAY_AFTER_SEND); #endif #if defined(DECODE_BEO) diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index e96beb259..99acf3f23 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -506,6 +506,21 @@ rawData[36]: + 500 Sum: 23300 +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 +Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711); +rawData[58]: + -1032900 + +2650,- 900 + + 450,- 450 + 450,- 450 + 450,- 850 +1400,-1300 + + 950,- 850 + 500,- 400 + 950,- 400 + 500,- 450 + + 450,- 850 + 500,- 400 + 500,- 400 + 950,- 850 + + 500,- 400 + 500,- 400 + 950,- 450 + 450,- 450 + + 450,- 450 + 450,- 400 + 500,- 850 + 500,- 400 + + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400 + + 500,- 850 + 950,- 450 + 450,- 850 + 500 +Sum: 36850 + 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 diff --git a/examples/UnitTest/UnitTest_64bit.log b/examples/UnitTest/UnitTest_64bit.log index 96c2bffea..7def9abbc 100644 --- a/examples/UnitTest/UnitTest_64bit.log +++ b/examples/UnitTest/UnitTest_64bit.log @@ -524,6 +524,21 @@ rawData[36]: + 550 Sum: 23450 +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 +Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711); +rawData[58]: + -1032900 + +2650,- 900 + + 450,- 450 + 450,- 450 + 450,- 850 +1400,-1300 + + 950,- 850 + 500,- 400 + 950,- 400 + 500,- 450 + + 450,- 850 + 500,- 400 + 500,- 400 + 950,- 850 + + 500,- 400 + 500,- 400 + 950,- 450 + 450,- 450 + + 450,- 450 + 450,- 400 + 500,- 850 + 500,- 400 + + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400 + + 500,- 850 + 950,- 450 + 450,- 850 + 500 +Sum: 36850 + 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! diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 7a2bebddd..2a903bfe3 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -57,6 +57,7 @@ typedef enum { KASEIKYO_MITSUBISHI, RC5, RC6, + RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ SAMSUNG, /* 20*/ SAMSUNGLG, SAMSUNG48, @@ -131,6 +132,8 @@ struct IRData { 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; diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index e8c7a554c..5f724c45b 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -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"; @@ -80,7 +81,7 @@ const char string_FAST[] PROGMEM = "FAST"; const char *const ProtocolNames[] PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, string_LG2, string_NEC, string_NEC2, string_Onkyo, string_Panasonic, string_Kaseikyo, string_Kaseikyo_Denon, string_Kaseikyo_Sharp, - string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_SamsungLG, string_Samsung48, + 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 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 1fb0ec6ce..380563b00 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1582,8 +1582,8 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(F("SB_FIRST, , ")); } #endif -#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) - if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && decodedIRData.protocol == KASEIKYO) { +#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6) + if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A)) { aSerial->print(F(", 0x")); aSerial->print(decodedIRData.extra, HEX); } diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 716d4ebc2..7a35ffa19 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -99,7 +99,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. @@ -569,6 +569,7 @@ class IRsend { void sendRC5(uint8_t aAddress, uint8_t aCommand, 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); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 2cc8dd43f..424f52c82 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -8,6 +8,8 @@ ************************************************************************************ * MIT License * + * Copyright (c) 2020-2024 Armin Joachimsmeyer + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -243,8 +245,8 @@ bool IRrecv::decodeRC5() { + 450 Sum: 23150 */ -// Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause -// Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits (=31bits) + 2666us pause +// Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit +// Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits + 2666us pause - 37 bits incl. start bit // !!! toggle bit has another timing :-( !!! // mark->space => 1 // space->mark => 0 @@ -261,8 +263,10 @@ bool IRrecv::decodeRC5() { #define RC6_TOGGLE_BIT_INDEX RC6_MODE_BITS // fourth position, index = 3 #define RC6_ADDRESS_BITS 8 #define RC6_COMMAND_BITS 8 +#define RC6_CUSTOMER_BITS 14 #define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 21 +#define RC6A_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + 1 + RC6_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 36 #define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444) @@ -388,6 +392,57 @@ void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe } } +/** + * Assemble raw data for RC6 from parameters and toggle state and send + * We do not wait for the minimal trailing space of 2666 us + * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. + */ +void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aCustomer, + bool aEnableAutomaticToggle) { + + LongUnion tIRRawData; + tIRRawData.UByte.LowByte = aCommand; + tIRRawData.UByte.MidLowByte = aAddress; + + tIRRawData.UWord.HighWord = aCustomer | 0x400; // bit 31 is always 1 + + if (aEnableAutomaticToggle) { + if (sLastSendToggleValue == 0) { + sLastSendToggleValue = 1; + // set toggled bit + IR_DEBUG_PRINT(F("Set Toggle ")); + tIRRawData.UByte.HighByte |= 0x80; // toggle bit is bit 32 + } else { + sLastSendToggleValue = 0; + } + } + + // Set mode bits + uint64_t tRawData = tIRRawData.ULong + 0x0600000000; + +#if defined(LOCAL_DEBUG) + Serial.print(F("RC6A: ")); + Serial.print(F("sLastSendToggleValue=")); + Serial.print (sLastSendToggleValue); + Serial.print(F(" RawData=")); + Serial.println(tIRRawData.ULong, HEX); +#endif + + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; + while (tNumberOfCommands > 0) { + + // start and leading bits are sent by sendRC6 + sendRC6Raw(tRawData, RC6A_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6 + + tNumberOfCommands--; + // skip last delay! + if (tNumberOfCommands > 0) { + // send repeated command in a fixed raster + delay(RC6_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI); + } + } +} + /** * Try to decode data as RC6 protocol */ @@ -482,7 +537,7 @@ bool IRrecv::decodeRC6() { tValue.ULong = tDecodedRawData; decodedIRData.decodedRawData = tDecodedRawData; - if (tBitIndex < 36) { + if (tBitIndex < 35) { // RC6 8 address bits, 8 command bits decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; decodedIRData.command = tValue.UByte.LowByte; @@ -494,21 +549,23 @@ bool IRrecv::decodeRC6() { if (tBitIndex > 20) { decodedIRData.flags |= IRDATA_FLAGS_EXTRA_INFO; } + decodedIRData.protocol = RC6; + } else { - // RC6A - 32 bits - decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; - if ((tValue.UByte.MidLowByte & 0x80) != 0) { - decodedIRData.flags = IRDATA_FLAGS_TOGGLE_BIT | IRDATA_FLAGS_IS_MSB_FIRST; - } - tValue.UByte.MidLowByte &= 0x87F; // mask toggle bit + // RC6A + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO; decodedIRData.command = tValue.UByte.LowByte; decodedIRData.address = tValue.UByte.MidLowByte; + decodedIRData.extra = tValue.UWord.HighWord & 0x3FFF; // Mask to 14 bits, remove toggle and constant 1 + if ((tValue.UByte.HighByte & 0x80) != 0) { + decodedIRData.flags |= IRDATA_FLAGS_TOGGLE_BIT; + } + decodedIRData.protocol = RC6A; } // check for repeat, do not check toggle bit yet checkForRepeatSpaceTicksAndSetFlag(RC6_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK); - decodedIRData.protocol = RC6; return true; } diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index a670f55d5..aaf2ed969 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -44,15 +44,17 @@ /* * Functions declared here */ -void timerResetInterruptPending(); -void timerEnableReceiveInterrupt(); -void timerDisableReceiveInterrupt(); -void timerConfigForReceive(); -void enableSendPWMByTimer(); -void disableSendPWMByTimer(); -void timerConfigForSend(uint16_t aFrequencyKHz); - -// SEND_PWM_BY_TIMER is defined in IRremote.hpp line 195. +void timerConfigForReceive(); // Initialization of 50 us timer, interrupts are still disabled +void timerEnableReceiveInterrupt(); // Enable interrupts of an initialized timer +void timerDisableReceiveInterrupt(); // Disable interrupts of an initialized timer +void timerResetInterruptPending(); // ISR helper function for some architectures, which require a manual reset + // of the pending interrupt (TIMER_REQUIRES_RESET_INTR_PENDING is defined). Otherwise empty. + +void timerConfigForSend(uint16_t aFrequencyKHz); // Initialization of timer hardware generated PWM, if defined(SEND_PWM_BY_TIMER) +void enableSendPWMByTimer(); // Switch on PWM generation +void disableSendPWMByTimer(); // Switch off PWM generation + +// SEND_PWM_BY_TIMER for different architectures is enabled / defined at IRremote.hpp line 195. #if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) ) #define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here. #endif @@ -1485,7 +1487,7 @@ void timerDisableReceiveInterrupt() { #undef ISR # endif -# if !defined(DISABLE_CODE_FOR_RECEIVER) // &IRReceiveTimerInterruptHandler is referenced, but not available +# if !defined(DISABLE_CODE_FOR_RECEIVER) // Otherwise the &IRReceiveTimerInterruptHandler is referenced, but not available void timerConfigForReceive() { // ESP32 has a proper API to setup timers, no weird chip macros needed // simply call the readable API versions :) From 95a29e453099cca7c447e4ec9861a5dec4d84bb2 Mon Sep 17 00:00:00 2001 From: alastaira Date: Mon, 7 Oct 2024 12:48:55 +0100 Subject: [PATCH 064/133] Update IRremote.hpp (#1265) Updated to use local reference for ir_DistanceWidthProtocol.hpp for consistency/to prevent errors if not installed in global Arduino libraries location. --- src/IRremote.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 657f06878..43f3d5d76 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -306,7 +306,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) From bd19150960cf466cbf205d0d74d19b01582f295c Mon Sep 17 00:00:00 2001 From: Armin Date: Mon, 7 Oct 2024 14:21:31 +0200 Subject: [PATCH 065/133] Housekeeping for ATtinies and ESP32 --- .github/workflows/LibraryBuild.yml | 98 +++++++++---------- README.md | 13 ++- changelog.md | 4 +- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 10 +- examples/ControlRelay/PinDefinitionsAndMore.h | 10 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 10 +- .../PinDefinitionsAndMore.h | 10 +- examples/MicroGirs/PinDefinitionsAndMore.h | 10 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 10 +- .../PinDefinitionsAndMore.h | 10 +- .../PinDefinitionsAndMore.h | 10 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 10 +- examples/ReceiveDemo/ReceiveDemo.ino | 35 +++++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 10 +- .../PinDefinitionsAndMore.h | 10 +- .../SendAndReceive/PinDefinitionsAndMore.h | 10 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 10 +- examples/SendDemo/PinDefinitionsAndMore.h | 10 +- examples/SendDemo/SendDemo.ino | 4 +- .../PinDefinitionsAndMore.h | 10 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 10 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 10 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 10 +- .../PinDefinitionsAndMore.h | 10 +- .../SimpleReceiverForHashCodes.ino | 6 ++ .../PinDefinitionsAndMore.h | 10 +- examples/SimpleSender/PinDefinitionsAndMore.h | 10 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 10 +- examples/TinySender/PinDefinitionsAndMore.h | 10 +- examples/UnitTest/PinDefinitionsAndMore.h | 10 +- src/IRFeedbackLED.hpp | 10 +- src/IRReceive.hpp | 3 +- src/IRremoteInt.h | 5 +- src/TinyIRReceiver.hpp | 13 +-- src/digitalWriteFast.h | 19 ++-- src/private/IRTimer.hpp | 2 +- 36 files changed, 244 insertions(+), 208 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index c6dbb9b0f..1ca9d9f2d 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -60,13 +60,13 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect -# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll -# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled -# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll + - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro -# - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 -# - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal # https://github.com/SpenceKonde/megaTinyCore/issues/935 + - 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 @@ -176,45 +176,43 @@ jobs: # # 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 + build-properties: # the flags were put in compiler.cpp.extra_flags + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 + + - 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 # # 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 + + - 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 # # MegaCore @@ -237,19 +235,19 @@ 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 +# 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 + IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 + All: -DRAW_BUFFER_LENGTH=750 -MMD -c - 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 +# 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 + IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 + All: -DRAW_BUFFER_LENGTH=750 -MMD -c # # STM @@ -303,10 +301,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/README.md b/README.md index 1694220ef..4520ffc78 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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#3tutorials) - [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) @@ -49,7 +50,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#other-libraries) + * [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) @@ -64,7 +65,7 @@ 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 receiver and sender instances](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver-and-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) @@ -304,6 +305,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. @@ -458,7 +463,7 @@ If the record gap determined by `RECORD_GAP_MICROS` is changed from the default 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 +### 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. @@ -668,7 +673,7 @@ 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 +## Multiple IR receiver and sender instances **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.
diff --git a/changelog.md b/changelog.md index 50d3d8747..3ba38d7ea 100644 --- a/changelog.md +++ b/changelog.md @@ -2,8 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.4.2 + # 4.4.1 -- Support for ESP 3.0 by akellai. +- 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(). diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 99468db8d..d2cf21b92 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -65,6 +65,22 @@ #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! +#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 // @@ -72,7 +88,7 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it requires 750. Default is 200. # if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) -#define RAW_BUFFER_LENGTH 730 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 +#define RAW_BUFFER_LENGTH 730 // This big value is required to allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 # endif #endif @@ -158,7 +174,7 @@ void setup() { Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed")); Serial.print(MARK_EXCESS_MICROS); Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding")); -#endif +#endif // FLASHEND >= 0x3FFF } void loop() { @@ -172,8 +188,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 @@ -255,28 +270,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(), maybe other platforms (not tested yet) too. +# 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 +# else IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource. tone(TONE_PIN, 2200, 8); delay(8); IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked. +# endif # endif -#endif } +#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 */ diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 362326401..03cdfab9c 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-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -194,7 +194,6 @@ 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.flush(); @@ -260,6 +259,7 @@ void loop() { 0, 0); #endif delay(DELAY_AFTER_SEND); +#endif Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first")); Serial.flush(); diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index 1766e7c3f..b58a29455 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. /* diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 14573c786..2dad3f4d9 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -35,7 +35,7 @@ * 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 @@ -93,10 +93,10 @@ // 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 diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index ff83b762b..0e68965a2 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -108,10 +108,11 @@ IRAM_ATTR void setFeedbackLED(bool aSwitchLedOn) { if (aSwitchLedOn) { if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) { + // Turn user defined pin LED on #if defined(FEEDBACK_LED_IS_ACTIVE_LOW) - digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED on + if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);} #else - digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH); // Turn user defined pin LED on + if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);} #endif #if defined(LED_BUILTIN) // use fast macros here } else { @@ -124,10 +125,11 @@ void setFeedbackLED(bool aSwitchLedOn) { } } else { if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) { + // Turn user defined pin LED off #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, HIGH);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);} #else - digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); // Turn user defined pin LED off + if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);} #endif #if defined(LED_BUILTIN) } else { diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 380563b00..d144733f7 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -340,8 +340,9 @@ 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) diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 7a35ffa19..185f2fc3a 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -73,7 +73,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 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 39b3414e3..e65158595 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -114,17 +114,18 @@ 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) @@ -323,7 +324,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 @@ -336,7 +337,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 diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index 043ae7150..a36a71f34 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -11,6 +11,14 @@ #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 @@ -29,10 +37,6 @@ #include // declarations for the fallback to digitalWrite(), digitalRead() etc. -#if defined(MEGATINYCORE) -#error Do not use "#include digitalWriteFast.h" because megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast(). -#endif - // --- Arduino Mega and ATmega128x/256x based boards --- #if (defined(ARDUINO_AVR_MEGA) || \ defined(ARDUINO_AVR_MEGA1280) || \ @@ -316,12 +320,6 @@ #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) @@ -420,4 +418,5 @@ if (__builtin_constant_p(P)) { \ # endif #endif // !defined(digitalToggleFast) +#endif // !defined(MEGATINYCORE) #endif //__digitalWriteFast_h_ diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index aaf2ed969..92c162e43 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -196,7 +196,7 @@ void disableSendPWMByTimer() { // ATtiny84 #elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny88__) # if !defined(IR_USE_AVR_TIMER1) -#define IR_USE_AVR_TIMER1 // send pin = pin 6 +#define IR_USE_AVR_TIMER1 // send pin = pin 6, no tone() available when using ATTinyCore # endif #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) From 71d9a2c3b1098dbac30ad97c9adbf11f9e7cfbfa Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 13 Oct 2024 10:36:47 +0200 Subject: [PATCH 066/133] Examples --- .github/workflows/LibraryBuild.yml | 80 +++++++++---------- README.md | 31 ++++--- examples/AllProtocolsOnLCD/ADCUtils.hpp | 2 + .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 9 ++- examples/ControlRelay/PinDefinitionsAndMore.h | 9 ++- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 9 ++- .../PinDefinitionsAndMore.h | 9 ++- examples/MicroGirs/PinDefinitionsAndMore.h | 9 ++- .../ReceiveAndSend/PinDefinitionsAndMore.h | 9 ++- .../PinDefinitionsAndMore.h | 9 ++- .../PinDefinitionsAndMore.h | 9 ++- examples/ReceiveDemo/PinDefinitionsAndMore.h | 9 ++- examples/ReceiveDemo/ReceiveDemo.ino | 22 +++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 9 ++- .../PinDefinitionsAndMore.h | 9 ++- .../SendAndReceive/PinDefinitionsAndMore.h | 9 ++- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 9 ++- examples/SendDemo/PinDefinitionsAndMore.h | 9 ++- .../PinDefinitionsAndMore.h | 9 ++- .../SendProntoDemo/PinDefinitionsAndMore.h | 9 ++- examples/SendRawDemo/PinDefinitionsAndMore.h | 9 ++- .../SimpleReceiver/PinDefinitionsAndMore.h | 9 ++- examples/SimpleReceiver/SimpleReceiver.ino | 16 ++-- .../PinDefinitionsAndMore.h | 9 ++- .../SimpleReceiverForHashCodes.ino | 15 +++- .../PinDefinitionsAndMore.h | 9 ++- examples/SimpleSender/PinDefinitionsAndMore.h | 9 ++- examples/TinyReceiver/PinDefinitionsAndMore.h | 9 ++- examples/TinySender/PinDefinitionsAndMore.h | 9 ++- examples/UnitTest/PinDefinitionsAndMore.h | 9 ++- src/private/IRTimer.hpp | 6 +- 31 files changed, 245 insertions(+), 143 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 1ca9d9f2d..ab187e158 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -60,13 +60,13 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect - - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro - - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal - - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal +# - 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 @@ -176,43 +176,43 @@ jobs: # # megaTinyCore # - - 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 - build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 - - - 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 +# build-properties: # the flags were put in compiler.cpp.extra_flags +# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 + +# - 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 # # 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,SimpleReceiverForHashCodes.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,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 +# - 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 + +# - 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 # # MegaCore @@ -235,7 +235,6 @@ 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: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 @@ -243,7 +242,6 @@ jobs: - 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: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 @@ -287,7 +285,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 diff --git a/README.md b/README.md index 4520ffc78..c0e416ec6 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Protocols can be switched off and on by defining macros before the line `#includ - 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. @@ -446,7 +446,7 @@ On a long press, the **SamsungLG protocol** does not repeat its frame, it sends ## 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**. @@ -519,7 +519,8 @@ If you do not know which protocol your IR transmitter uses, you have several cho
# 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 @@ -568,9 +569,15 @@ 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 +The receiver uses a **pin change interrupt** for on-the-fly decoding which limits the choice of protocols.
+On each level change, the current level and the time since the last change are used to incrementally decode the protocol.
+With this operating principle, we **always need a stop bit**! +The level change caused by this stop bit triggers the final decoding and the call of the optional **user-provided callback function** `handleTinyReceivedIRData()`. + 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`. @@ -651,7 +658,7 @@ 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. @@ -693,7 +700,7 @@ 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.
+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 @@ -712,7 +719,7 @@ The **[SimpleReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote/blob 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. +The **[SimpleReceiverForHashCodes](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino)** 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 @@ -747,7 +754,7 @@ Sends all available protocols at least once. 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()`. +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 Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.
@@ -915,7 +922,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! @@ -1000,7 +1007,7 @@ For non AVR boards/platforms you must look for the appropriate section guarded b ### 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 IR timer is restarted after the tone has stopped. +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. @@ -1014,7 +1021,7 @@ This works on AVR boards like Uno because each call to` tone()` completely initi 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**. +**Exeptions** are currently [ESP32, ARDUINO_ARCH_RP2040, PARTICLE and ARDUINO_ARCH_MBED](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleSender/PinDefinitionsAndMore.h#L334), 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): @@ -1049,7 +1056,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)**. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 73030b475..ebf190267 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -607,6 +607,8 @@ uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageM /* * 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(); diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index d2cf21b92..b0e6abb17 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -224,7 +224,12 @@ void loop() { } 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 */ @@ -244,11 +249,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 + } } } diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 36d79a6fd..74d0c225f 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-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -104,9 +104,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 +117,14 @@ 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) { + // do something + } else if (IrReceiver.decodedIRData.command == 0x11) { + // do something else + } } } } diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index b58a29455..8e4f5a60a 100644 --- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -87,10 +87,17 @@ void loop() { * Finally, check the received data and perform actions according to the received command */ auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs - if (tDecodedRawData == 0x4F7BE2FB) { - // do something - } else if (tDecodedRawData == 0x97483BFB) { - // 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 { + 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 2dad3f4d9..11b677350 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 2dad3f4d9..11b677350 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -192,9 +192,12 @@ #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){ diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 92c162e43..c2d555d87 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1437,17 +1437,17 @@ void timerConfigForReceive() { **********************************************************/ #elif defined(ESP32) # if !defined(ESP_ARDUINO_VERSION) -#define ESP_ARDUINO_VERSION 0 +#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1 # endif # if !defined(ESP_ARDUINO_VERSION_VAL) -#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) 202 +#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) # endif // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() -# if !defined(SEND_LEDC_CHANNEL) +# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif From 80d7cc3516c7212c94ecc1d804ec0dd27a2b8b87 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 30 Oct 2024 14:53:23 +0100 Subject: [PATCH 067/133] Documentation --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c0e416ec6..74f268129 100644 --- a/README.md +++ b/README.md @@ -573,10 +573,12 @@ For applications only requiring NEC, NEC variants or FAST -see below- protocol, which has very **small code size of 500 bytes and does NOT require any timer**. ## Principle of operation -The receiver uses a **pin change interrupt** for on-the-fly decoding which limits the choice of protocols.
-On each level change, the current level and the time since the last change are used to incrementally decode the protocol.
-With this operating principle, we **always need a stop bit**! -The level change caused by this stop bit triggers the final decoding and the call of the optional **user-provided callback function** `handleTinyReceivedIRData()`. +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** `handleTinyReceivedIRData()`.
+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`. From 29613aced6d75b87a4a7a8aa35dc70bc705888ca Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 3 Nov 2024 19:44:35 +0100 Subject: [PATCH 068/133] Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4) --- .github/workflows/LibraryBuild.yml | 8 ++++++ README.md | 2 +- changelog.md | 1 + .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 2 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/MicroGirs/PinDefinitionsAndMore.h | 2 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 2 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/SimpleSender/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 2 +- examples/TinySender/PinDefinitionsAndMore.h | 2 +- src/TinyIRReceiver.hpp | 6 ++-- src/private/IRTimer.hpp | 28 ++++++++++--------- 28 files changed, 52 insertions(+), 39 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index ab187e158..ba2dd15a6 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -57,6 +57,7 @@ jobs: - 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 @@ -153,6 +154,13 @@ jobs: 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 + build-properties: # the flags were put in compiler.cpp.extra_flags + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 + + - arduino-boards-fqbn: arduino:mbed:nano33ble build-properties: # the flags were put in compiler.cpp.extra_flags IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 diff --git a/README.md b/README.md index 74f268129..d7af27a7d 100644 --- a/README.md +++ b/README.md @@ -906,7 +906,7 @@ 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) - Sparkfun Pro Micro diff --git a/changelog.md b/changelog.md index 3ba38d7ea..a62ab7300 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.4.2 +- Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4) # 4.4.1 - Support for ESP core 3.x by akellai. diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 11b677350..9c5e9772e 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -39,7 +39,7 @@ * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore - * SAMD21 3 4 5 + * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index e65158595..85481b46b 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -84,7 +84,7 @@ //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. -#include "TinyIR.h" // If not defined, it defines IR_RECEIVE_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT +#include "TinyIR.h" #include "digitalWriteFast.h" /** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol @@ -110,6 +110,8 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; /* * Set input pin and output pin definitions etc. */ +//#define IR_RECEIVE_PIN 2 +//#define IR_FEEDBACK_LED_PIN LED_BUILTIN #if defined(IR_INPUT_PIN) #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN" #define IR_RECEIVE_PIN IR_INPUT_PIN @@ -129,7 +131,7 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; #endif #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN) -#define IR_FEEDBACK_LED_PIN LED_BUILTIN +#define IR_FEEDBACK_LED_PIN LED_BUILTIN #endif #if !( \ diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index c2d555d87..6e708a615 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -48,7 +48,7 @@ void timerConfigForReceive(); // Initialization of 50 us timer, interr void timerEnableReceiveInterrupt(); // Enable interrupts of an initialized timer void timerDisableReceiveInterrupt(); // Disable interrupts of an initialized timer void timerResetInterruptPending(); // ISR helper function for some architectures, which require a manual reset - // of the pending interrupt (TIMER_REQUIRES_RESET_INTR_PENDING is defined). Otherwise empty. +// of the pending interrupt (TIMER_REQUIRES_RESET_INTR_PENDING is defined). Otherwise empty. void timerConfigForSend(uint16_t aFrequencyKHz); // Initialization of timer hardware generated PWM, if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer(); // Switch on PWM generation @@ -1581,8 +1581,13 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { # if !defined(IR_SAMD_TIMER) # if defined(__SAMD51__) +# if defined(TC5) #define IR_SAMD_TIMER TC5 #define IR_SAMD_TIMER_IRQ TC5_IRQn +# else +#define IR_SAMD_TIMER TC3 +#define IR_SAMD_TIMER_IRQ TC3_IRQn +# endif # else // SAMD21 #define IR_SAMD_TIMER TC3 @@ -1617,7 +1622,11 @@ void timerConfigForReceive() { # if defined(__SAMD51__) // Enable the TC5 clock, use generic clock generator 0 (F_CPU) for TC5 +# if defined(TC5_GCLK_ID) GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); +# else + GCLK->PCHCTRL[TC3_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); +# endif // The TC should be disabled before the TC is reset in order to avoid undefined behavior. TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable the Timer @@ -1674,18 +1683,12 @@ void timerConfigForReceive() { } # if !defined(DISABLE_CODE_FOR_RECEIVER) -# if defined(__SAMD51__) -void TC5_Handler(void) { - TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER; - // Check for right interrupt bit - if (TC->INTFLAG.bit.MC0 == 1) { - // reset bit for next turn - TC->INTFLAG.bit.MC0 = 1; - IRReceiveTimerInterruptHandler(); - } -} +# if defined(__SAMD51__) && defined(TC5) +void TC5_Handler(void) # else -void TC3_Handler(void) { +void TC3_Handler(void) +# endif // defined(__SAMD51__) +{ TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER; // Check for right interrupt bit if (TC->INTFLAG.bit.MC0 == 1) { @@ -1694,7 +1697,6 @@ void TC3_Handler(void) { IRReceiveTimerInterruptHandler(); } } -# endif // defined(__SAMD51__) # endif // !defined(DISABLE_CODE_FOR_RECEIVER) /*************************************** From e623510d086cbd40e276b28c7f150b23affeed01 Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 6 Nov 2024 13:01:59 +0100 Subject: [PATCH 069/133] attachInterrupt() on SAMD has a different Semantic :-( see: https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax --- changelog.md | 3 ++- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 5 ++++ examples/ControlRelay/PinDefinitionsAndMore.h | 5 ++++ .../IRDispatcherDemo/PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ examples/MicroGirs/PinDefinitionsAndMore.h | 5 ++++ .../ReceiveAndSend/PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ examples/ReceiveDemo/PinDefinitionsAndMore.h | 5 ++++ examples/ReceiveDump/PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ .../ReceiverTimingAnalysis.ino | 4 ++++ .../SendAndReceive/PinDefinitionsAndMore.h | 5 ++++ .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 5 ++++ examples/SendDemo/PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ .../SendProntoDemo/PinDefinitionsAndMore.h | 5 ++++ examples/SendRawDemo/PinDefinitionsAndMore.h | 5 ++++ .../SimpleReceiver/PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ .../PinDefinitionsAndMore.h | 5 ++++ examples/SimpleSender/PinDefinitionsAndMore.h | 5 ++++ examples/TinyReceiver/PinDefinitionsAndMore.h | 5 ++++ examples/TinySender/PinDefinitionsAndMore.h | 5 ++++ examples/UnitTest/PinDefinitionsAndMore.h | 7 +++++- src/TinyIRReceiver.hpp | 24 +++++++++++-------- 27 files changed, 141 insertions(+), 12 deletions(-) diff --git a/changelog.md b/changelog.md index a62ab7300..e3e907568 100644 --- a/changelog.md +++ b/changelog.md @@ -3,7 +3,8 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.4.2 -- Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4) +- 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/. # 4.4.1 - Support for ESP core 3.x by akellai. diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index c0efd284f..01245b139 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -70,7 +70,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 9c5e9772e..5e9328296 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 9c5e9772e..5e9328296 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -39,6 +39,7 @@ * 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 @@ -288,7 +289,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 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 11b677350..5e9328296 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -39,7 +39,8 @@ * 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 2 3 4 @@ -288,7 +289,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 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 85481b46b..d32d023c1 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -70,12 +70,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 */ @@ -92,13 +86,18 @@ */ #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 #define LOCAL_TRACE_STATE_MACHINE #else +//#define LOCAL_TRACE // This enables trace output only for this file //#define LOCAL_TRACE_STATE_MACHINE // to see the state of the ISR (Interrupt Service Routine) state machine #endif @@ -571,14 +570,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 @@ -586,11 +590,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); From 403d3ee21f13041c4c6774c7243abb33b0dd5156 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 28 Nov 2024 21:38:48 +0100 Subject: [PATCH 070/133] fixes #1272 Sharp frame marker --- .github/workflows/PlatformIoPublish.yml | 1 - changelog.md | 2 +- examples/ControlRelay/ControlRelay.ino | 2 -- examples/ReceiveDemo/ReceiveDemo.ino | 5 ++-- .../ReceiverTimingAnalysis.ino | 11 ++++--- examples/SendDemo/SendDemo.ino | 3 +- examples/SendProntoDemo/SendProntoDemo.ino | 7 +++-- examples/TinyReceiver/TinyReceiver.ino | 10 +++++-- examples/UnitTest/UnitTest.ino | 9 ++++-- library.json | 14 +++++---- src/IRremoteInt.h | 3 +- src/ir_Denon.hpp | 30 +++++++++++++------ 12 files changed, 61 insertions(+), 36 deletions(-) diff --git a/.github/workflows/PlatformIoPublish.yml b/.github/workflows/PlatformIoPublish.yml index cc9b32a1a..00cc577ec 100644 --- a/.github/workflows/PlatformIoPublish.yml +++ b/.github/workflows/PlatformIoPublish.yml @@ -40,4 +40,3 @@ jobs: # run: | # pio package pack # pio package publish --owner arminjo --non-interactive - \ No newline at end of file diff --git a/changelog.md b/changelog.md index e3e907568..b759322aa 100644 --- a/changelog.md +++ b/changelog.md @@ -95,7 +95,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. 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/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index b0e6abb17..1ee81fdb7 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -126,13 +126,12 @@ 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*/ \ + #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)); diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index 01245b139..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__)); diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 03cdfab9c..5049e4bfd 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -52,13 +52,12 @@ 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)); diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index d4893f033..e935d00c1 100644 --- a/examples/SendProntoDemo/SendProntoDemo.ino +++ b/examples/SendProntoDemo/SendProntoDemo.ino @@ -59,8 +59,11 @@ 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)); diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index d8c440d44..a81d33f55 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -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(); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index af464aa51..dfc0fb596 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -123,12 +123,15 @@ void setup() { pinMode(DEBUG_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) - 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/library.json b/library.json index cda754b22..dbfb3f3ef 100644 --- a/library.json +++ b/library.json @@ -1,15 +1,14 @@ { "name": "IRremote", - "keywords": "communication, infrared, ir, remote", + "version": "4.4.1", "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.1", - "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"], + "headers": "IRRemote.hpp", + "examples": "examples/*/*.ino", + "export": {"exclude": [".github", "pictures"]} } diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 185f2fc3a..983964e6e 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -540,7 +540,7 @@ 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)."))); @@ -580,6 +580,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); diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index f22141145..ba95babf6 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -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. @@ -113,19 +113,31 @@ DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_L * Start of send and decode functions ************************************/ +/* + * Maybe minimal number of repeats is 1 for a press to be reliable detected by some devices + */ 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 packets are always sent twice. A non inverted and then an inverted frame. + * If you specify a repeat of e.g. 3, then 6 frames are sent. + */ +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 @@ -200,8 +212,8 @@ bool IRrecv::decodeDenon() { * Here we are in the auto repeated frame with the inverted command */ #if defined(LOCAL_DEBUG) - Serial.print(F("Denon: ")); - Serial.println(F("Autorepeat received=")); + Serial.print(F("Denon: ")); + Serial.println(F("Autorepeat received=")); #endif decodedIRData.flags |= IRDATA_FLAGS_IS_AUTO_REPEAT; // Check parity of consecutive received commands. There is no parity in one data set. @@ -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) { From 363878d1e215898730abebc0c13d76463eed052e Mon Sep 17 00:00:00 2001 From: Armin Date: Wed, 4 Dec 2024 15:29:07 +0100 Subject: [PATCH 071/133] QA + Denon repeats --- .github/workflows/PlatformIoPublish.yml | 4 ++-- examples/AllProtocolsOnLCD/ADCUtils.hpp | 2 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 -- .../IRDispatcherDemo/IRCommandDispatcher.hpp | 2 +- .../IRDispatcherDemo/IRDispatcherDemo.ino | 2 -- .../IRremoteExtensionTest.ino | 9 ++++--- examples/IRremoteInfo/IRremoteInfo.ino | 10 +++++--- examples/MicroGirs/MicroGirs.ino | 2 -- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 -- .../ReceiveAndSendDistanceWidth.ino | 2 -- .../ReceiveAndSendHob2Hood.ino | 2 -- examples/ReceiveDump/ReceiveDump.ino | 10 +++++--- .../ReceiveOneAndSendMultiple.ino | 2 -- examples/SendAndReceive/SendAndReceive.ino | 2 -- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 2 -- .../SendLGAirConditionerDemo.ino | 5 ++-- examples/SendRawDemo/SendRawDemo.ino | 2 -- examples/SimpleReceiver/SimpleReceiver.ino | 2 -- .../SimpleReceiverForHashCodes.ino | 2 -- .../SimpleReceiverWithCallback.ino | 2 -- examples/SimpleSender/SimpleSender.ino | 2 -- examples/TinySender/TinySender.ino | 2 -- src/IRProtocol.hpp | 2 +- src/IRReceive.hpp | 2 +- src/IRSend.hpp | 2 +- src/TinyIRSender.hpp | 2 +- src/ir_BoseWave.hpp | 2 +- src/ir_Denon.hpp | 24 ++++++++++--------- src/ir_DistanceWidthProtocol.hpp | 2 +- src/ir_FAST.hpp | 2 +- src/ir_JVC.hpp | 2 +- src/ir_Kaseikyo.hpp | 2 +- src/ir_LG.hpp | 2 +- src/ir_MagiQuest.hpp | 2 +- src/ir_NEC.hpp | 2 +- src/ir_Pronto.hpp | 2 +- src/ir_RC5_RC6.hpp | 2 +- src/ir_Samsung.hpp | 2 +- src/ir_Sony.hpp | 2 +- 39 files changed, 55 insertions(+), 73 deletions(-) diff --git a/.github/workflows/PlatformIoPublish.yml b/.github/workflows/PlatformIoPublish.yml index 00cc577ec..d8727408c 100644 --- a/.github/workflows/PlatformIoPublish.yml +++ b/.github/workflows/PlatformIoPublish.yml @@ -36,7 +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 +# pio package publish --owner Arduino-IRremote --non-interactive diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index ebf190267..9cf096bcd 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -58,7 +58,7 @@ 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 diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index c70463de2..7a115c45b 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -137,8 +137,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) diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp index 701103a1f..5901c6a90 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 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/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index 3ec197ad8..d40c69ad3 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -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/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..a468d0265 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -292,8 +292,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 diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index ee4dc7519..dad106fd0 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -114,8 +114,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) diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index c0d9da014..146e34c1e 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -89,8 +89,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) diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index 159dad611..f9b3a2b09 100644 --- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -74,8 +74,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) diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index d0451baa2..dc2357783 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -65,13 +65,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)); diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index a4a584f06..e11a0875e 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -104,8 +104,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) diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 9e99353dc..9b80ab7ed 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -53,8 +53,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) diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index a7eafb3d6..5046b96cf 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -110,8 +110,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) diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index 90511f282..a92e45e21 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -67,13 +67,12 @@ 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))); diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 8e1847517..5b03a6438 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -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) diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 74d0c225f..b4ca0ba69 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -72,8 +72,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)); diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index 8e4f5a60a..91819446b 100644 --- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -54,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)); diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index a857203f2..a126d6422 100644 --- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino +++ b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino @@ -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/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index d73b37485..553053633 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -29,8 +29,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)); 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/src/IRProtocol.hpp b/src/IRProtocol.hpp index 5f724c45b..c14c93a77 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 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index d144733f7..2c2e6bd85 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -33,7 +33,7 @@ #ifndef _IR_RECEIVE_HPP #define _IR_RECEIVE_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 diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 66813366d..3b25c0d89 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -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 diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 65a1fe18b..86f308ac1 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -48,7 +48,7 @@ //#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 diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index c8ec9b7a1..8035a61c7 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 diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index ba95babf6..bca43f416 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 @@ -113,9 +113,6 @@ DENON_BIT_MARK, DENON_ONE_SPACE, DENON_BIT_MARK, DENON_ZERO_SPACE, PROTOCOL_IS_L * Start of send and decode functions ************************************/ -/* - * Maybe minimal number of repeats is 1 for a press to be reliable detected by some devices - */ void IRsend::sendSharp(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { sendDenon(aAddress, aCommand, aNumberOfRepeats, 1); // see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/1272 @@ -126,8 +123,10 @@ void IRsend::sendSharp2(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberO } /* - * Denon packets are always sent twice. A non inverted and then an inverted frame. - * If you specify a repeat of e.g. 3, then 6 frames are sent. + * 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 @@ -152,12 +151,15 @@ void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOf sendPulseDistanceWidthData(&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(&DenonProtocolConstants, tData, DENON_BITS); + } bool IRrecv::decodeSharp() { diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index aa2d4ed24..4ce2c0fc7 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -62,7 +62,7 @@ #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 diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index f9ea167cd..bd5518b89 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 diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 614cc00c7..39e8b1dd3 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 diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index fe61f63e1..023030145 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 diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 52df1dbd0..812b96058 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -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 diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index 291f80869..28d40c408 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -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 diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index b02931cc7..62b9e6ac2 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -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. diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index b7b31d271..620829ed5 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -34,7 +34,7 @@ #ifndef _IR_PRONTO_HPP #define _IR_PRONTO_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 diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 424f52c82..35506699d 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -32,7 +32,7 @@ #ifndef _IR_RC5_RC6_HPP #define _IR_RC5_RC6_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 diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index eaa6e921b..6856ec4a7 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -32,7 +32,7 @@ #ifndef _IR_SAMSUNG_HPP #define _IR_SAMSUNG_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 diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index 59b7a8f74..3a06948a8 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -30,7 +30,7 @@ #ifndef _IR_SONY_HPP #define _IR_SONY_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 From d7acf29ac067aec5207e35b39c222fa1f80a4210 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 25 Dec 2024 15:35:15 +0100 Subject: [PATCH 072/133] Documentation --- README.md | 17 +++- examples/AllProtocolsOnLCD/ADCUtils.h | 3 + examples/AllProtocolsOnLCD/ADCUtils.hpp | 26 +++--- .../IRDispatcherDemo/IRCommandDispatcher.hpp | 2 +- examples/TinyReceiver/TinyReceiver.ino | 2 +- keywords.txt | 80 ++++++++++++----- src/IRFeedbackLED.hpp | 2 +- src/IRReceive.hpp | 49 ++++++---- src/IRSend.hpp | 14 +-- src/IRremoteInt.h | 4 +- src/TinyIRReceiver.hpp | 2 +- src/digitalWriteFast.h | 90 ++++++++++--------- src/ir_BoseWave.hpp | 2 +- src/ir_Denon.hpp | 2 +- src/ir_FAST.hpp | 2 +- src/ir_JVC.hpp | 2 +- src/ir_Kaseikyo.hpp | 2 +- src/ir_Lego.hpp | 2 +- src/ir_MagiQuest.hpp | 2 +- src/ir_NEC.hpp | 2 +- src/ir_Others.hpp | 4 +- src/ir_Samsung.hpp | 2 +- src/ir_Sony.hpp | 2 +- src/ir_Template.hpp | 2 +- src/private/IRTimer.hpp | 10 +-- 25 files changed, 198 insertions(+), 129 deletions(-) diff --git a/README.md b/README.md index d7af27a7d..e461a1ac9 100644 --- a/README.md +++ b/README.md @@ -222,6 +222,17 @@ 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!

@@ -833,6 +844,7 @@ 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. | | `IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK` | disabled | Saves up to 60 bytes of program memory and 2 bytes RAM. | @@ -847,7 +859,6 @@ Modify them by enabling / disabling them, or change the values if applicable. | `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | | `USE_ACTIVE_HIGH_OUTPUT_FOR_SEND_PIN` | disabled | Only if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. | | `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | -| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST and LEGO_PF from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | | `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | | `MICROS_PER_TICK` | 50 | Resolution of the raw input buffer data. Corresponds to 2 pulses of each 26.3 µs at 38 kHz. | @@ -858,7 +869,7 @@ 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. | @@ -866,7 +877,7 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `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. | 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 9cf096bcd..8d0e5e799 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -28,7 +28,7 @@ #include "ADCUtils.h" #if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected -#if !defined(STR_HELPER) +#if !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif @@ -403,7 +403,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 +472,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 +483,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 +519,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 +547,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 +558,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 +579,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 +588,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,12 +597,12 @@ 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; } /* diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp index 5901c6a90..a8006400e 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp +++ b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp @@ -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/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index a81d33f55..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 diff --git a/keywords.txt b/keywords.txt index 935f913e1..adfe84678 100644 --- a/keywords.txt +++ b/keywords.txt @@ -16,35 +16,40 @@ 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 sendJVC KEYWORD2 sendLG KEYWORD2 -sendLGRepeat KEYWORD2 +sendLG2 KEYWORD2 +sendLG2Repeat KEYWORD2 sendLGRaw KEYWORD2 sendNEC KEYWORD2 +sendNEC2 KEYWORD2 sendNECRepeat KEYWORD2 sendNECRaw KEYWORD2 sendOnkyo KEYWORD2 @@ -67,18 +72,41 @@ sendMagiQuest KEYWORD2 sendPronto KEYWORD2 sendMagiQuest KEYWORD2 sendFAST 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 +115,26 @@ 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 + +FEEDBACK_LED_IS_ACTIVE_LOW LITERAL1 + +RAW_BUFFER_LENGTH LITERAL1 +EXCLUDE_UNIVERSAL_PROTOCOLS LITERAL1 +EXCLUDE_EXOTIC_PROTOCOLS LITERAL1 +SEND_PWM_BY_TIMER LITERAL1 +USE_NO_SEND_PWM LITERAL1 IR_RECEIVE_PIN LITERAL1 IR_SEND_PIN LITERAL1 -FEEDBACK_LED_IS_ACTIVE_LOW LITERAL1 +USE_CALLBACK_FOR_TINY_RECEIVER LITERAL1 diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 0e68965a2..0db0c02f8 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -47,7 +47,7 @@ struct FeedbackLEDControlStruct { struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED control instance /** - * Enable blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving + * Enables 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 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 2c2e6bd85..cb3c5525b 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -199,9 +199,9 @@ void IRReceiveTimerInterruptHandler() { irparams.StateForISR = IR_REC_STATE_STOP; #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 @@ -235,9 +235,9 @@ void IRReceiveTimerInterruptHandler() { 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 @@ -286,6 +286,7 @@ ISR() /********************************************************************************************************************** * Stream like API **********************************************************************************************************************/ + /** * Initializes the receive and feedback pin * @param aReceivePin The Arduino pin number, where a demodulating IR receiver is connected. @@ -342,12 +343,16 @@ void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) { #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 :-( - if (__builtin_constant_p(aReceivePinNumber) ) { pinModeFast(aReceivePinNumber, INPUT);} else { pinModeFast(aReceivePinNumber, INPUT);} + 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; @@ -375,7 +380,7 @@ 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 @@ -398,7 +403,7 @@ 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. @@ -415,6 +420,10 @@ void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) { 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; timerConfigForReceive(); // no interrupts enabled here! @@ -519,16 +528,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; } } @@ -1076,16 +1085,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. @@ -1166,7 +1175,7 @@ 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. */ @@ -1284,8 +1293,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) */ @@ -1318,6 +1327,10 @@ 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, ")); diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 3b25c0d89..b9a4b786e 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -408,7 +408,7 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma } /** - * 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) { @@ -429,7 +429,7 @@ void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLe } /** - * 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) { @@ -700,7 +700,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 +719,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 { @@ -753,7 +753,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc * @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 NULL, the first frame is repeated completely, otherwise this function is used for sending the repeat frame. + * @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, @@ -761,7 +761,7 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader void (*aSpecialSendRepeatFunction)()) { if (aNumberOfRepeats < 0) { - if (aSpecialSendRepeatFunction != NULL) { + if (aSpecialSendRepeatFunction != nullptr) { aSpecialSendRepeatFunction(); return; } else { @@ -776,7 +776,7 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); - if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != NULL) { + if (tNumberOfCommands < ((uint_fast8_t) aNumberOfRepeats + 1) && aSpecialSendRepeatFunction != nullptr) { // send special repeat aSpecialSendRepeatFunction(); } else { diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 983964e6e..dbf140a04 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -507,11 +507,11 @@ class IRsend { 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); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index d32d023c1..97b7b61f6 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -62,7 +62,7 @@ * - 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 diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index a36a71f34..f745081aa 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -324,18 +324,22 @@ int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Paramete # 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 @@ -346,28 +350,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 @@ -379,17 +387,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 @@ -400,18 +402,22 @@ 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)) diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index 8035a61c7..0843331de 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -48,7 +48,7 @@ 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 }; + , (BOSEWAVE_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index bca43f416..0f64a0aba 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -107,7 +107,7 @@ 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 }; + (DENON_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index bd5518b89..e5cee6ea3 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -65,7 +65,7 @@ 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 }; +nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 39e8b1dd3..3c1516797 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -80,7 +80,7 @@ #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 }; +JVC_ONE_SPACE, JVC_BIT_MARK, JVC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 023030145..01ce36c9c 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -120,7 +120,7 @@ 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 }; + , (KASEIKYO_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 1885f3bfa..410bf8001 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -85,7 +85,7 @@ 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 }; + / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index 28d40c408..e16f84420 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -111,7 +111,7 @@ // 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 }; +nullptr }; //+============================================================================= // /** diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 62b9e6ac2..eb3d52983 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -122,7 +122,7 @@ struct PulseDistanceWidthProtocolConstants NECProtocolConstants = // Like NEC but repeats are full frames instead of special NEC repeats struct PulseDistanceWidthProtocolConstants NEC2ProtocolConstants = { NEC2, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, -NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL }; +NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index cc5291b04..e6b24b872 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -59,7 +59,7 @@ #define DISH_REPEAT_SPACE 6200 // really? struct PulseDistanceWidthProtocolConstants DishProtocolConstants = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, -DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 40, NULL }; +DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 40, nullptr }; void IRsend::sendDish(uint16_t aData) { sendPulseDistanceWidth(&DishProtocolConstants, aData, DISH_BITS, 4); @@ -85,7 +85,7 @@ void IRsend::sendDish(uint16_t aData) { #define WHYNTER_ZERO_SPACE 750 struct PulseDistanceWidthProtocolConstants WhynterProtocolConstants = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, -WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, NULL }; +WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, nullptr }; void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) { sendPulseDistanceWidth(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend); diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 6856ec4a7..2ca504dab 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -104,7 +104,7 @@ // 19 byte RAM struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, - (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL }; + (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; struct PulseDistanceWidthProtocolConstants SamsungLGProtocolConstants = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index 3a06948a8..af9e6bc58 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -91,7 +91,7 @@ #define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms struct PulseDistanceWidthProtocolConstants SonyProtocolConstants = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK, -SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), NULL }; +SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/ir_Template.hpp b/src/ir_Template.hpp index 9855f51a3..82bad807a 100644 --- a/src/ir_Template.hpp +++ b/src/ir_Template.hpp @@ -125,7 +125,7 @@ // use BOSEWAVE, we have no SHUZU code struct PulseDistanceWidthProtocolConstants ShuzuProtocolConstants = { BOSEWAVE, 38, SHUZU_HEADER_MARK, SHUZU_HEADER_SPACE, SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SHUZU_REPEAT_PERIOD - / MICROS_IN_ONE_MILLI), NULL }; + / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 6e708a615..872c4eddf 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1445,7 +1445,7 @@ void timerConfigForReceive() { // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. -hw_timer_t *s50usTimer = NULL; // set by timerConfigForReceive() +hw_timer_t *s50usTimer = nullptr; // set by timerConfigForReceive() # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels @@ -1464,7 +1464,7 @@ void timerEnableReceiveInterrupt() { * Special support for ESP core < 202 */ void timerDisableReceiveInterrupt() { - if (s50usTimer != NULL) { + if (s50usTimer != nullptr) { timerDetachInterrupt(s50usTimer); timerEnd(s50usTimer); } @@ -1472,7 +1472,7 @@ void timerDisableReceiveInterrupt() { # else void timerDisableReceiveInterrupt() { - if (s50usTimer != NULL) { + if (s50usTimer != nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) timerStop(s50usTimer); # else @@ -1492,7 +1492,7 @@ void timerConfigForReceive() { // ESP32 has a proper API to setup timers, no weird chip macros needed // simply call the readable API versions :) // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true - if(s50usTimer == NULL) { + if(s50usTimer == nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. timerStop(s50usTimer); // Stop it here, to avoid "error E (3447) gptimer: gptimer_start(348): timer is not enabled yet" at timerEnableReceiveInterrupt() @@ -1775,7 +1775,7 @@ bool IRTimerInterruptHandlerHelper(repeating_timer_t*) { } void timerEnableReceiveInterrupt() { - add_repeating_timer_us(-(MICROS_PER_TICK), IRTimerInterruptHandlerHelper, NULL, &s50usTimer); + add_repeating_timer_us(-(MICROS_PER_TICK), IRTimerInterruptHandlerHelper, nullptr, &s50usTimer); } void timerDisableReceiveInterrupt() { cancel_repeating_timer(&s50usTimer); From ee75848c8803f40b29c38d6f55d44d268dbba3bb Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 26 Dec 2024 23:42:49 +0100 Subject: [PATCH 073/133] closes #1279 --- README.md | 2 +- src/TinyIRReceiver.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e461a1ac9..d869ef3f6 100644 --- a/README.md +++ b/README.md @@ -588,7 +588,7 @@ Instead of sampling the input every 50 µs as IRremote does, TinyReceiver r 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** `handleTinyReceivedIRData()`.
+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.
diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 97b7b61f6..7d4f0b114 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -151,7 +151,7 @@ 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 From 1c3096ef76dc6c379d76bb91a21ada6709bc9b92 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 23 Jan 2025 11:50:55 +0100 Subject: [PATCH 074/133] Documentation --- README.md | 32 ++++++++++++++++++-------------- src/IRremote.h | 13 +++++++------ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d869ef3f6..97216d84f 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,13 @@ 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.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) @@ -112,12 +113,15 @@ 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**. +# 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. -## New features with version 4.x +# 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.x - **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead. - New universal **Pulse Distance / Pulse Width / Pulse Distance Width decoder** added, which covers many previous unknown protocols. - Printout of code how to send received command by `IrReceiver.printIRSendUsage(&Serial)`. @@ -127,11 +131,11 @@ 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). @@ -150,7 +154,7 @@ 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. @@ -257,7 +261,7 @@ Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `s
-# Errors with using the 4.x versions for old tutorials +## 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. diff --git a/src/IRremote.h b/src/IRremote.h index 3af3f5829..997ab3714 100644 --- a/src/IRremote.h +++ b/src/IRremote.h @@ -33,16 +33,17 @@ bool IRrecv::decode(decode_results *aResults) { 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("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("**************************************************************************************************")); From f24fe098f2a86fd9c2bd759b70d465a4da1dc4e0 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 3 Mar 2025 22:50:06 +0100 Subject: [PATCH 075/133] Improved examples --- README.md | 2 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 +- .../IRremoteExtensionClass.cpp | 2 +- .../IRremoteExtensionTest.ino | 2 +- examples/MicroGirs/MicroGirs.ino | 2 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 41 ++++++++++++------- .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 6 +-- examples/ReceiveDump/ReceiveDump.ino | 2 +- examples/SimpleReceiver/SimpleReceiver.ino | 6 ++- .../SimpleReceiverWithCallback.ino | 2 +- src/IRremote.h | 13 +++--- 12 files changed, 47 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 97216d84f..aa5f82481 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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#3tutorials) +- [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) diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 7a115c45b..36c5648bb 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -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 diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 8a315e9c7..f2f8cef46 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -36,7 +36,7 @@ * 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) diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index d40c69ad3..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 diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index a468d0265..ca2a9b18a 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 diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index dad106fd0..a5f3adbba 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,14 +72,14 @@ // #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. @@ -129,8 +129,9 @@ void setup() { 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); + 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() { @@ -167,6 +168,7 @@ void loop() { // Restart receiver Serial.println(F("Button released -> start receiving")); IrReceiver.start(); + delay(100); // Button debouncing } else if (IrReceiver.decode()) { /* @@ -177,7 +179,6 @@ void loop() { } sSendButtonWasActive = tSendButtonIsActive; - delay(100); } // Stores the code for later playback in sStoredIRData @@ -200,21 +201,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 + 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.decodedIRData.rawDataPtr->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 code and store ")); + Serial.print(IrReceiver.decodedIRData.rawDataPtr->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); @@ -224,7 +235,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); @@ -232,7 +244,6 @@ 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 */ diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 146e34c1e..78a999ad1 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -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) diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 1ee81fdb7..a3b2ecb40 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 @@ -86,9 +86,9 @@ // #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 730 // This big value is required to allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 +#define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index dc2357783..b01010626 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -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 730 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 # endif diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index b4ca0ba69..6d4d40a65 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.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 @@ -62,7 +62,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. /* * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures @@ -119,8 +119,10 @@ void loop() { 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/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino index a126d6422..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 diff --git a/src/IRremote.h b/src/IRremote.h index 997ab3714..3cc42969c 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,7 +30,7 @@ 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:")); From 87201d6d11b30ee30140218340f98a515c5c64bd Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 5 Mar 2025 01:45:58 +0100 Subject: [PATCH 076/133] Fixed overflow handling. Improved repeat detection for DistanceWidthProtocol --- changelog.md | 2 + .../IRremoteExtensionClass.cpp | 4 +- .../IRremoteExtensionClass.h | 2 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 +- .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 1 - examples/UnitTest/UnitTest.ino | 4 +- examples/UnitTest/UnitTest.log | 1148 +++++++++-------- src/IRProtocol.h | 6 +- src/IRProtocol.hpp | 53 +- src/IRReceive.hpp | 91 +- src/IRremoteInt.h | 12 +- src/TinyIR.h | 6 +- src/ir_DistanceWidthProtocol.hpp | 8 +- 14 files changed, 712 insertions(+), 629 deletions(-) diff --git a/changelog.md b/changelog.md index b759322aa..c1514191e 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 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. # 4.4.1 - Support for ESP core 3.x by akellai. diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index f2f8cef46..ef95f8fe0 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -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..73e8c5f69 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h @@ -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/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index a5f3adbba..591579d85 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -248,7 +248,7 @@ void sendCode(storedIRDataStruct *aIRDataToSend) { * Use the write function, which does the switch for different protocols */ IrSender.write(&aIRDataToSend->receivedIRData); - printIRResultShort(&Serial, &aIRDataToSend->receivedIRData, false); + printIRResultShort(&Serial, &aIRDataToSend->receivedIRData); } } diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 78a999ad1..d096a459c 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -79,7 +79,7 @@ #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 +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; diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index a3b2ecb40..f66a10a70 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -96,7 +96,6 @@ //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active //#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory - // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. //#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity. diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index dfc0fb596..e66d4fcbb 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -888,9 +888,9 @@ void loop() { * 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 } diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 99acf3f23..4063d890c 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -12,129 +12,129 @@ 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 Duration=67850 us Send with: IrSender.sendNEC(0xF1, 0x76, ); -rawData[68]: +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 - + 600 -Sum: 67800 + +8950,-4350 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650 +Duration=67850 us 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 Duration=73350 us 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 +rawData[68]: + -1060600 + +8950,-4400 + + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650 +Duration=73350 us 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 Duration=73400 us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: - -1059050 +rawData[68]: + -1061100 +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 - + 600 -Sum: 73300 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650 +Duration=73400 us Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants -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 Duration=54150 us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1062700 - +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 +rawData[100]: + -1064750 + +3500,-1650 + + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 350 + + 500,-1250 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 500,- 350 + 500,-1250 + 450,- 400 + 500,-1250 + 450 -Sum: 54150 +Duration=54150 us Send Panasonic 0xB, 0x10 as 48 bit PulseDistance -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 Duration=53200 us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1079300 +rawData[100]: + -1081400 +3450,-1650 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 550,- 300 + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,- 350 + 550,- 300 + 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 + + 500,- 350 + 500,- 350 + 500,- 350 + 550,- 350 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 300 + + 550,-1150 + 500,- 400 + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 400 + 450,-1200 + 500,- 350 + 500,-1200 + + 550,- 300 + 500,-1200 + 500,- 350 + 500,-1200 + 500 -Sum: 53200 +Duration=53200 us -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 Duration=53200 us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1074200 +rawData[100]: + -1076300 +3450,-1650 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,- 350 + 550,-1150 + 500,- 400 + 500,- 300 + + 550,- 300 + 550,- 300 + 500,- 350 + 550,- 300 + 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,- 350 + 500,- 350 + 550,- 300 + 500,- 400 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 300 + 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,- 350 + 500,-1200 + 500,- 350 + 500,-1200 + 500 -Sum: 53200 +Duration=53200 us Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first -Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first -Send on a 8 bit platform with: +Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first Duration=138400 us +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 + IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4400, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); +rawData[148]: + -1081200 + +8900,-4400 + + 600,-1600 + 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 @@ -142,105 +142,105 @@ rawData[148]: + 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 + + 650,-1600 + 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 + + 550,-1700 + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650 - + 600,-1650 + 550,-1650 + 600,-1650 + 600,-1650 + + 550,-1650 + 600,-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 + 600 -Sum: 138350 +Duration=138400 us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first -Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first -Send on a 8 bit platform with: +Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Duration=48250 us +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 + IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); +rawData[108]: + -1118250 + + 350,- 550 + + 400,- 500 + 700,- 200 + 650,- 250 + 700,- 200 + + 650,- 250 + 400,- 550 + 650,- 250 + 650,- 250 + + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 + + 650,- 250 + 650,- 200 + 400,- 550 + 650,- 200 + + 400,- 550 + 650,- 200 + 400,- 550 + 650,- 200 + + 700,- 200 + 400,- 550 + 350,- 550 + 650,- 250 + 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 + + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 550 + + 400,- 550 + 650,- 250 + 650,- 200 + 400,- 500 + + 700,- 200 + 400,- 550 + 650,- 250 + 350,- 550 + + 350,- 550 + 350,- 550 + 650,- 250 + 400,- 500 + + 700,- 250 + 650,- 250 + 350,- 550 + 350,- 550 + + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 + + 400 +Duration=48250 us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data -Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first -Send on a 8 bit platform with: +Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Duration=48500 us +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 + IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); +rawData[108]: + -1097950 + 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 + + 400,- 500 + 650,- 250 + 650,- 250 + 650,- 250 + + 650,- 250 + 400,- 500 + 700,- 200 + 700,- 250 + + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 + + 650,- 250 + 650,- 250 + 350,- 550 + 650,- 250 + + 350,- 550 + 650,- 250 + 350,- 550 + 650,- 250 + + 650,- 250 + 400,- 550 + 350,- 500 + 650,- 250 + + 400,- 500 + 400,- 500 + 400,- 550 + 650,- 250 + + 650,- 200 + 700,- 200 + 650,- 250 + 400,- 550 + + 400,- 500 + 650,- 250 + 650,- 250 + 400,- 550 + + 600,- 250 + 400,- 500 + 650,- 250 + 400,- 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 - -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, , ); -rawData[18]: - -1092450 - +5950,- 500 - +1500,- 500 + 500,-1450 + 550,-1450 +1550,- 450 + + 350,- 550 + 650,- 250 + 350,- 550 + 400,- 500 + + 650 +Duration=48500 us + +Send 7 bit ASCII character with PulseDistanceWidth LSB first +Protocol=PulseDistance Raw-Data=0x76 7 bits LSB first Duration=20950 us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 6000, 450, 550, 1450, 1550, 450, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , ); +rawData[18]: + -1095750 + +6000,- 450 + +1550,- 450 + 550,-1400 + 550,-1450 +1550,- 450 + 550,-1450 + 550,-1450 + 550,-1450 + 550 -Sum: 20950 +Duration=20950 us Send Sony12 as PulseWidth LSB first -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 Duration=21050 us Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: - -1036550 - +2450,- 600 - + 600,- 550 +1250,- 550 +1250,- 550 + 650,- 550 +rawData[26]: + -1038650 + +2500,- 500 + + 700,- 500 +1250,- 550 +1250,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 +1250 -Sum: 21050 +Duration=21050 us Send 32 bit PulseWidth 0x87654321 LSB first -Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first -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 - +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,- 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 - -Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first +Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first Duration=24650 us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1100, 450, 650, 250, 350, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); +rawData[66]: + -1038250 + +1100,- 450 + + 600,- 300 + 350,- 250 + 350,- 250 + 400,- 200 + + 400,- 250 + 600,- 300 + 350,- 250 + 350,- 250 + + 650,- 250 + 650,- 250 + 400,- 250 + 350,- 250 + + 350,- 250 + 400,- 200 + 650,- 250 + 400,- 250 + + 650,- 250 + 350,- 250 + 650,- 250 + 350,- 250 + + 350,- 250 + 650,- 250 + 700,- 200 + 400,- 250 + + 650,- 200 + 700,- 200 + 700,- 200 + 400,- 250 + + 350,- 250 + 350,- 250 + 400,- 200 + 700 +Duration=24650 us + +Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first Duration=63850 us Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); rawData[112]: @@ -259,129 +259,152 @@ rawData[112]: + 300,- 850 + 600,- 550 + 600,- 550 + 350,- 800 + 300,- 850 + 350,- 800 + 350,- 800 + 600,- 550 + 600,- 550 + 350,- 800 + 350,- 800 + 600 -Sum: 63850 +Duration=63850 us 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 Duration=76750 us Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); -rawData[68]: - -1084150 +rawData[68]: + -1115300 +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 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + 600 -Sum: 76750 +Duration=76750 us 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 Duration=72250 us 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 +rawData[68]: + -1060250 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + 600 -Sum: 72200 +Duration=72250 us 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 Duration=64450 us Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); -rawData[100]: - -1057800 - +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 - + 450 -Sum: 64400 +rawData[100]: + -1059900 + +3500,-1650 + + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 400 + + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,-1250 + 500,-1200 + + 500,-1200 + 500,-1250 + 500,-1200 + 500,-1250 + + 500,- 400 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,- 400 + 450,- 400 + 500,-1250 + + 450,-1250 + 500,- 350 + 500,- 400 + 450,-1250 + + 500 +Duration=64450 us 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 Duration=69550 us Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); -rawData[100]: - -1078000 +rawData[100]: + -1080100 +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 - + 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,-1200 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,- 400 + 450,- 400 + + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1300 + + 450,- 400 + 500,-1200 + 500,-1250 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1250 + + 450,-1250 + 500,- 400 + 450,- 400 + 500,-1200 + 500 -Sum: 69550 +Duration=69550 us 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 Duration=67900 us 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 - + 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 +rawData[100]: + -1080850 + +3500,-1650 + + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 + + 500,-1250 + 450,- 400 + 500,-1200 + 500,- 400 + + 500,- 350 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 500,-1200 + 500,-1250 + 500,-1250 + + 450,-1250 + 500,-1250 + 500,-1200 + 500,-1250 + + 500,- 350 + 500,-1250 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,-1250 + 500,-1200 + 500,- 350 + + 500,-1250 + 500,- 350 + 500,- 350 + 500,-1250 + + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 + 500 -Sum: 67850 +Duration=67900 us 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 Duration=23150 us Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: - -1076500 +rawData[32]: + -1078600 + 300,-1750 + 300,- 750 + 300,- 750 + 300,- 750 - + 300,-1750 + 300,- 750 + 300,-1800 + 250,-1800 - + 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750 - + 300,- 750 + 300,- 750 + 300,- 750 + 300 -Sum: 23150 + + 300,-1750 + 350,- 700 + 350,-1700 + 350,-1750 + + 300,- 750 + 300,-1750 + 350,-1700 + 350,-1750 + + 300,- 750 + 300,- 750 + 300,- 700 + 350 +Duration=23150 us Send Denon/Sharp variant -Protocol=Sharp Address=0x11 Command=0x76 Raw-Data=0x4ED1 15 bits LSB first -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 - + 300,- 750 + 300,-1750 + 300,-1800 + 300,-1750 - + 300,- 750 + 300,- 750 + 300,-1750 + 300 -Sum: 24150 +Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x2ED1 15 bits LSB first Duration=24200 us +Send with: IrSender.sendDenon(0x11, 0x76, ); +rawData[32]: + -1020800 + + 300,-1750 + 350,- 700 + 350,- 700 + 300,- 750 + + 300,-1750 + 350,- 700 + 350,-1700 + 350,-1750 + + 350,- 700 + 300,-1750 + 350,-1750 + 300,-1750 + + 350,- 700 + 350,-1700 + 350,- 700 + 350 +Duration=24200 us 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 Duration=21050 us +Send with: IrSender.sendSony(0x11, 0x76, 2, 12); +rawData[26]: + -1023000 + +2450,- 550 + + 700,- 500 +1300,- 500 +1250,- 550 + 650,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + + 700,- 500 + 600,- 600 + 650,- 550 +1250 +Duration=21050 us + +Send Sony/SIRCS with 7 command and 8 address bits +Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Duration=26450 us +Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); +rawData[32]: + -1038750 + +2450,- 550 + + 700,- 500 +1250,- 550 +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 +Duration=26450 us + +Send Sony/SIRCS with 7 command and 5 address bits +Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Duration=21050 us Send with: IrSender.sendSony(0x11, 0x76, 2, 12); rawData[26]: -1020900 @@ -389,10 +412,10 @@ rawData[26]: + 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 +Duration=21050 us 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 Duration=26450 us Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); rawData[32]: -1036650 @@ -401,10 +424,10 @@ rawData[32]: +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250 -Sum: 26450 +Duration=26450 us 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 Duration=35400 us Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20); rawData[42]: -1040400 @@ -414,112 +437,95 @@ rawData[42]: + 650,- 550 + 600,- 600 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250 -Sum: 35400 - -Send Samsung 8 bit command and 8 bit address -Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first -Send with: IrSender.sendSamsung(0xF1, 0x76, ); -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 +Duration=35400 us 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 Duration=69000 us 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 +rawData[68]: + -1057350 + +4550,-4350 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 + + 650 +Duration=69000 us 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 Duration=95900 us Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); -rawData[100]: - -1060250 - +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,- 500 + 600,-1650 + 600,-1650 + 600,- 500 - + 600 -Sum: 95800 +rawData[100]: + -1039600 + +4550,-4400 + + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600 + + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650 + + 650,- 500 + 600,- 500 + 650,- 500 + 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,- 450 + + 650 +Duration=95900 us 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 Duration=23200 us 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 +rawData[20]: + -1078850 + + 950,- 850 + +1850,-1700 +1800,- 850 + 950,- 850 + 950,-1700 + + 950,- 850 + 950,- 800 +1850,-1700 + 950,- 850 + +1850 +Duration=23200 us 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 Duration=23150 us Send with: IrSender.sendRC5(0x11, 0x76, ); -rawData[20]: - -1035650 - +1800,-1700 - + 950,- 850 +1800,- 850 + 950,- 850 + 900,-1750 - + 950,- 850 + 900,- 850 +1800,-1750 + 950,- 850 - +1800 -Sum: 23100 +rawData[20]: + -1037700 + +1850,-1700 + + 950,- 850 +1800,- 850 + 950,- 800 + 950,-1750 + + 950,- 800 + 950,- 850 +1800,-1750 + 950,- 800 + +1850 +Duration=23150 us 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 Duration=23300 us Send with: IrSender.sendRC6(0xF1, 0x76, ); -rawData[36]: - -1033000 - +2650,- 850 +rawData[36]: + -1035050 + +2700,- 800 + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850 - +1350,- 450 + 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=23300 us 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 +Protocol=RC6A Address=0xF1 Command=0x76 Extra=0x2711 Toggle=1 Raw-Data=0xA711F176 35 bits MSB first Duration=36800 us Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711); -rawData[58]: - -1032900 - +2650,- 900 - + 450,- 450 + 450,- 450 + 450,- 850 +1400,-1300 - + 950,- 850 + 500,- 400 + 950,- 400 + 500,- 450 +rawData[58]: + -1045150 + +2700,- 800 + + 500,- 400 + 500,- 450 + 450,- 900 +1350,-1300 + + 950,- 850 + 500,- 400 + 900,- 400 + 500,- 450 + 450,- 850 + 500,- 400 + 500,- 400 + 950,- 850 - + 500,- 400 + 500,- 400 + 950,- 450 + 450,- 450 - + 450,- 450 + 450,- 400 + 500,- 850 + 500,- 400 - + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400 - + 500,- 850 + 950,- 450 + 450,- 850 + 500 -Sum: 36850 + + 500,- 400 + 500,- 400 +1000,- 400 + 450,- 400 + + 500,- 450 + 500,- 400 + 450,- 850 + 500,- 400 + + 500,- 400 +1000,- 800 +1000,- 400 + 450,- 450 + + 450,- 850 + 950,- 400 + 500,- 850 + 500 +Duration=36800 us Send Bang&Olufsen - ENABLE_BEO_WITHOUT_FRAME_GAP is enabled @@ -532,11 +538,11 @@ rawData[36]: + 250,-5950 + 200,-6000 + 200,-9050 + 250,-2900 + 250,-9000 + 250,-6000 + 250,-5950 + 250,-2850 + 250 -Sum: 105700 +Duration=105700 us 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 +Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Duration=115000 us Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, ); rawData[38]: -15250 @@ -546,95 +552,120 @@ rawData[38]: + 250,-2900 + 250,-9000 + 250,-6000 + 250,-5950 + 250,-2850 + 250,-9100 + 200,-5950 + 250,-2900 + 200,-12150 + 250 -Sum: 115000 +Duration=115000 us Send MagiQuest -Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first +Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Duration=63900 us Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -1088700 +rawData[112]: + -1089250 + 350,- 800 + 350,- 800 + 350,- 800 + 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 + 350,- 800 + 600,- 550 + 600,- 550 - + 600,- 550 + 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 - + 350,- 800 + 600,- 550 + 600,- 550 + 600 -Sum: 63850 + + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550 + + 350,- 750 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 300,- 850 + 350,- 800 + 650,- 500 + + 650,- 500 + 350,- 800 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 + + 350,- 800 + 350,- 800 + 650,- 550 + 300,- 800 + + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 500 + 350,- 850 + + 350,- 750 + 350,- 800 + 650,- 500 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 500 + 650 +Duration=63900 us 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 Duration=40400 us Send with: IrSender.sendJVC(0xF1, 0x76, ); -rawData[36]: - -1085250 - +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 +rawData[36]: + -1087300 + +8400,-4100 + + 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 + 600,- 450 + + 600 +Duration=40400 us 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 Duration=59450 us 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 - + 500,- 550 + 500,-1550 + 550,-1550 + 500,- 550 - + 500,-1550 + 550,-1550 + 500,-1550 + 550,- 500 +rawData[60]: + -1041500 + +9000,-4150 + + 500,-1550 + 550,-1500 + 550,-1550 + 550,-1500 + + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550 + + 550,-1500 + 550,- 500 + 550,- 500 + 550,-1550 + + 550,-1500 + 550,- 500 + 550,- 500 + 550,- 500 + + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 + + 550,- 500 + 550,-1500 + 550,-1550 + 550,- 500 + + 550,-1500 + 550,-1550 + 500,-1550 + 550,- 500 + 550 -Sum: 59400 +Duration=59450 us 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 Duration=26800 us Send with: IrSender.sendBoseWave(0x0, 0x76, ); -rawData[36]: - -1056200 +rawData[36]: + -1058350 +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,-1400 + 600,- 400 + + 600,-1400 + 550,-1400 + 600,-1400 + 600,- 400 + + 550,-1400 + 600,- 400 + 600,- 400 + 600,-1400 + + 550,- 400 + 600,- 400 + 600,- 400 + 600,-1400 + 550 -Sum: 26800 +Duration=26800 us 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 Duration=28900 us Send with: IrSender.sendFAST(0x0, 0x76, ); -rawData[36]: - -1040250 +rawData[36]: + -1042350 +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,- 500 + 600,-1500 + 550,-1550 + 550,- 500 + + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 + + 550,-1550 + 550,- 500 + 550,- 500 + 600,-1500 + + 550,- 500 + 550,- 500 + 600,- 450 + 550,-1550 + 550 -Sum: 28950 +Duration=28900 us -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 - + 200,- 500 - + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 500 - + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 550 +Try to increase the "RAW_BUFFER_LENGTH" value of 400 in ../src/UnitTest.cpp +rawData[400]: + -1041550 + + 300,- 500 + + 250,- 500 + 250,- 550 + 200,- 500 + 250,- 550 + 200,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + + 250,- 500 + 250,- 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 + 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 + 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 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 @@ -657,195 +688,210 @@ rawData[200]: + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 250 -Sum: 74500 +Duration=149550 us 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 Duration=67850 us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -3276750 - +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 +rawData[68]: + -1028850 + +8900,-4400 + + 650,- 500 + 650,-1600 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 650,- 450 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 450 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650 +Duration=67850 us -Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=65900us Raw-Data=0x78870DF2 32 bits LSB first +Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=67950us Raw-Data=0x78870DF2 32 bits LSB first Duration=67900 us 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 +rawData[68]: + -67950 + +8950,-4400 + + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550 + + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650 + + 600,-1650 + 600,- 550 + 600,-1600 + 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 + + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 + + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650 + + 600,-1650 + 650,-1600 + 650,-1600 + 600,- 500 + + 650 +Duration=67900 us 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 Duration=67800 us 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 +rawData[68]: + -1062200 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,- 450 + 650,- 500 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650 +Duration=67800 us 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 Duration=67850 us 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 - + 600 -Sum: 67750 +rawData[68]: + -1060650 + +8950,-4400 + + 650,- 500 + 600,-1650 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,- 500 + 650,-1600 + 600,-1600 + + 650,- 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=67850 us 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 Duration=62250 us 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 +rawData[68]: + -1061250 + +8950,-4400 + + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 450 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,- 500 + 650,- 500 + 650,- 450 + 650,-1600 + + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600 + 600 -Sum: 62150 +Duration=62250 us 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 Duration=71150 us 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 +rawData[68]: + -1059700 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1550 + + 650,- 500 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + 650 -Sum: 71100 +Duration=71150 us 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 Duration=59250 us 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 +rawData[100]: + -1059850 + +3500,-1650 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,- 350 + 500,- 400 + 500,- 350 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,-1250 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1200 + 500 -Sum: 59350 +Duration=59250 us 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 Duration=66200 us Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711); -rawData[100]: - -1077750 +rawData[100]: + -1079850 +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 - + 450 -Sum: 66100 + + 500,-1200 + 500,- 400 + 450,- 400 + 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,- 350 + + 500,-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 + 450,-1250 + + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 + + 500,- 400 + 450,-1250 + 500,- 350 + 500,-1250 + + 500 +Duration=66200 us 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 Duration=62750 us 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 - + 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 -Sum: 62700 +rawData[100]: + -1080600 + +3500,-1650 + + 500,- 350 + 500,- 400 + 500,-1200 + 500,- 400 + + 450,-1250 + 500,- 350 + 500,-1250 + 500,- 350 + + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 + + 500,- 350 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,- 400 + 450,-1250 + 500,- 350 + 500,- 400 + + 450,-1250 + 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 + 450,-1250 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + + 450,- 400 + 500,-1250 + 450,- 400 + 500,-1200 + + 500 +Duration=62750 us Send Denon -Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first +Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first Duration=22150 us 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 - + 300,-1750 + 300,- 750 + 300,- 750 + 300 -Sum: 22100 +rawData[32]: + -1078350 + + 350,- 700 + 300,-1750 + 350,- 700 + 350,- 700 + + 350,-1700 + 350,-1750 + 300,-1750 + 350,-1750 + + 300,- 750 + 300,- 700 + 350,- 700 + 350,- 700 + + 300,-1750 + 350,- 700 + 350,- 700 + 350 +Duration=22150 us Send Denon/Sharp variant -Protocol=Sharp Address=0x12 Command=0x87 Raw-Data=0x50F2 15 bits LSB first -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 +Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x30F2 15 bits LSB first Duration=23200 us +Send with: IrSender.sendDenon(0x12, 0x87, ); +rawData[32]: + -1020850 + + 350,- 700 + 350,-1750 + 300,- 700 + 350,- 700 + + 350,-1750 + 300,-1750 + 350,-1700 + 350,-1750 + + 300,- 750 + 300,- 750 + 300,- 700 + 350,- 700 + + 350,-1750 + 300,-1750 + 350,- 700 + 350 +Duration=23200 us + +Send Sony/SIRCS with 7 command and 5 address bits +Protocol=Sony Address=0x12 Command=0x7 Raw-Data=0x907 12 bits LSB first Duration=19850 us +Send with: IrSender.sendSony(0x12, 0x7, 2, 12); +rawData[26]: + -1022950 + +2450,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250 +Duration=19850 us + + diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 2a903bfe3..6b257dbd0 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -101,7 +101,7 @@ struct DistanceWidthTimingInfoStruct { #define IRDATA_FLAGS_IS_MSB_FIRST 0x80 ///< Value is mainly determined by the (known) protocol. #define IRDATA_FLAGS_IS_LSB_FIRST 0x00 -#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. +#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. @@ -115,7 +115,7 @@ struct IRData { #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. + IRRawDataType decodedRawDataArray[DECODED_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 @@ -171,7 +171,7 @@ 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. +void printIRResultShort(Print *aSerial, IRData *aIRDataPtr); // 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 c14c93a77..bbe4cc378 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -81,8 +81,8 @@ 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_RC6A, 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 #endif @@ -160,7 +160,7 @@ namespace PrintULL { * @param aPrintRepeatGap If true also print the gap before repeats. * */ -void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) { +void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) { aSerial->println(F("Overflow")); return; @@ -210,22 +210,6 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap #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 @@ -245,14 +229,37 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap aSerial->print(F(" bits")); if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) { - aSerial->println(F(" MSB first")); + aSerial->print(F(" MSB first")); } else { - aSerial->println(F(" LSB first")); + aSerial->print(F(" LSB first")); } + } - } else { - aSerial->println(); + /* + * 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->print(F("us")); + + uint16_t tSumOfDurationTicks = 0; + for (IRRawlenType i = 1; i < aIRDataPtr->rawlen; i++) { + tSumOfDurationTicks += aIRDataPtr->rawDataPtr->rawbuf[i]; } + aSerial->print(F(" Duration=")); + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->println(F("us")); +#else + aSerial->println(); +#endif } } diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index cb3c5525b..dfce94271 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -167,15 +167,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 = irparams.TickCounterForISR; 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 (irparams.StateForISR == IR_REC_STATE_MARK) { + // Timing mark here, rawlen is even if (tIRInputLevel != INPUT_MARK) { /* * Mark ended here. Record mark time in rawbuf array @@ -188,35 +191,18 @@ void IRReceiveTimerInterruptHandler() { 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 (irparams.StateForISR == IR_REC_STATE_SPACE) { + /* + * In space receiving here, rawlen is odd + * Check for timeout or overflow + */ + if (irparams.TickCounterForISR > 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 nullptr) - */ - if (irparams.ReceiveCompleteCallbackFunction != nullptr) { - 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 @@ -241,6 +227,17 @@ void IRReceiveTimerInterruptHandler() { 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 + irparams.rawbuf[irparams.rawlen++] = irparams.TickCounterForISR; // record space + irparams.StateForISR = IR_REC_STATE_MARK; + irparams.TickCounterForISR = 0; } } else if (irparams.StateForISR == IR_REC_STATE_STOP) { /* @@ -1181,8 +1178,9 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants */ 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; @@ -1398,14 +1396,13 @@ void printActiveIRProtocols(Print *aSerial) { * 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) { +bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) { // call no class function with same name - ::printIRResultShort(aSerial, &decodedIRData, aPrintRepeatGap); + ::printIRResultShort(aSerial, &decodedIRData); if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) { return checkForRecordGapsMicros(aSerial); } @@ -1651,6 +1648,25 @@ 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 += decodedIRData.rawDataPtr->rawbuf[i]; + } + aSerial->print(F("Duration=")); + if (aOutputMicrosecondsInsteadOfTicks) { + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->println(F("us")); + + } else { + aSerial->print(tSumOfDurationTicks, DEC); + aSerial->println(F(" ticks")); + } +} + /** * Dump out the timings in IrReceiver.decodedIRData.rawDataPtr->rawbuf[] array 8 values per line. * @@ -1731,12 +1747,17 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI } aSerial->println(); - aSerial->print(F("Sum: ")); + aSerial->print(F("Duration=")); if (aOutputMicrosecondsInsteadOfTicks) { - aSerial->println((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->println(F("us")); + } else { - aSerial->println(tSumOfDurationTicks, DEC); + aSerial->print(tSumOfDurationTicks, DEC); + aSerial->println(F(" ticks")); } + aSerial->println(); + } /** diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index dbf140a04..517c059e2 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -247,6 +247,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(); @@ -257,7 +258,7 @@ 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 aCheckForRecordGapsMicros = true); void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo); void printIRSendUsage(Print *aSerial); #if defined(__AVR__) @@ -358,10 +359,13 @@ class IRrecv { 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. }; diff --git a/src/TinyIR.h b/src/TinyIR.h index c01a67ab9..ccc9ba410 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. @@ -218,11 +218,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 /** diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 4ce2c0fc7..bea846768 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -434,8 +434,12 @@ 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 From f570ed233b584c63ffc5dd8d924e5a6ba17d2317 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sat, 8 Mar 2025 10:29:31 +0100 Subject: [PATCH 077/133] Added MultipleSendPins example --- .github/workflows/LibraryBuild.yml | 2 +- README.md | 8 +- changelog.md | 1 + .../MultipleSendPins/MultipleSendPins.ino | 94 +++++++++++++++++++ examples/SimpleSender/SimpleSender.ino | 3 +- src/IRProtocol.h | 1 + src/IRProtocol.hpp | 4 + src/IRremoteInt.h | 2 +- 8 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 examples/MultipleSendPins/MultipleSendPins.ino diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index ba2dd15a6..600535094 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -100,7 +100,7 @@ jobs: 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 ReceiveDemo: -DDECODE_ONKYO diff --git a/README.md b/README.md index aa5f82481..256003fcd 100644 --- a/README.md +++ b/README.md @@ -562,9 +562,10 @@ Most of the times, *device* and *subdevice* can be taken as upper and lower byte 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. +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). ### List of public IR code databases @@ -767,6 +768,9 @@ Receives all protocols and dumps the received signal in different flavors includ #### SendDemo Sends all available protocols at least once. +#### MultipleSendPins +Demonstrates sending IR codes toggling between 2 **different send pins**. + #### SendAndReceive Demonstrates **receiving while sending**. diff --git a/changelog.md b/changelog.md index c1514191e..4372d417e 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - 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(); # 4.4.1 - Support for ESP core 3.x by akellai. diff --git a/examples/MultipleSendPins/MultipleSendPins.ino b/examples/MultipleSendPins/MultipleSendPins.ino new file mode 100644 index 000000000..33566bcbc --- /dev/null +++ b/examples/MultipleSendPins/MultipleSendPins.ino @@ -0,0 +1,94 @@ +/* + * 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 + +#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/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index 553053633..c6d97d62d 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. diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 6b257dbd0..2d7654767 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -171,6 +171,7 @@ const __FlashStringHelper* getProtocolString(decode_type_t aProtocol); #else const char* getProtocolString(decode_type_t aProtocol); #endif +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); // A static function to be able to print send or copied received data. /* diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index bbe4cc378..9153be564 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -160,6 +160,10 @@ namespace PrintULL { * @param aPrintRepeatGap If true also print the gap before repeats. * */ +void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) { + (void) aPrintRepeatGap; + printIRResultShort(aSerial, aIRDataPtr); +} void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) { aSerial->println(F("Overflow")); diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 517c059e2..10a122444 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -470,7 +470,7 @@ class IRsend { // 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."))); + __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); From 5389c9d04a427d3466d92bff6f16f19652b1b914 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 19 Mar 2025 10:57:55 +0100 Subject: [PATCH 078/133] PulseDistanceWidthProtocolConstants now in PROGMEM --- .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/SendDemo/SendDemo.ino | 37 ++-- examples/UnitTest/UnitTest.ino | 29 +-- src/IRReceive.hpp | 28 +++ src/IRSend.hpp | 195 ++++++++++++++++++ src/IRremoteInt.h | 37 +++- src/TinyIRReceiver.hpp | 5 +- src/digitalWriteFast.h | 2 + src/ir_BoseWave.hpp | 12 +- src/ir_Denon.hpp | 14 +- src/ir_FAST.hpp | 21 +- src/ir_JVC.hpp | 10 +- src/ir_Kaseikyo.hpp | 16 +- src/ir_LG.hpp | 16 +- src/ir_Lego.hpp | 4 +- src/ir_MagiQuest.hpp | 16 +- src/ir_NEC.hpp | 23 +-- src/ir_Others.hpp | 12 +- src/ir_Samsung.hpp | 22 +- src/ir_Sony.hpp | 8 +- src/ir_Template.hpp | 12 +- 21 files changed, 391 insertions(+), 130 deletions(-) diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index d096a459c..a932e91ac 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -80,7 +80,7 @@ // Storage for the recorded code, pre-filled with NEC data 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 +DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing uint8_t sNumberOfBits = 32; bool sSendButtonWasActive; diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 5049e4bfd..724963f67 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -50,6 +50,10 @@ #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 +#endif + void setup() { Serial.begin(115200); @@ -145,7 +149,7 @@ 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 */ @@ -197,10 +201,9 @@ void loop() { Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); 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 + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant #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 #endif delay(DELAY_AFTER_SEND); @@ -212,24 +215,25 @@ void loop() { Serial.println(F(" LSB first")); Serial.flush(); #if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawData[0], 48, + IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawDataPGM[0], 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); + 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")); + 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); + IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, + NO_REPEATS); #endif delay(DELAY_AFTER_SEND); @@ -242,8 +246,10 @@ void loop() { 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); + 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); @@ -254,8 +260,7 @@ void loop() { 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); + IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); #endif delay(DELAY_AFTER_SEND); #endif @@ -364,7 +369,7 @@ void loop() { IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, 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. +#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(); @@ -389,14 +394,14 @@ void loop() { Serial.println(F("Send next protocols with IrSender.write")); Serial.flush(); - IRSendData.protocol = JVC; // switch protocol + IRSendData.protocol = JVC;// switch protocol Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); IrSender.write(&IRSendData, sRepeats); delay(DELAY_AFTER_SEND); - IRSendData.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/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index e66d4fcbb..fe9961079 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -119,6 +119,10 @@ volatile bool sDataJustReceived = false; void ReceiveCompleteCallbackHandler(); +#if __INT_WIDTH__ < 32 +IRRawDataType const tRawDataPGM[4] PROGMEM = { 0xB02002, 0xA010, 0x0, 0x0 }; // LSB of tRawData[0] is sent first +#endif + void setup() { pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP); @@ -130,7 +134,7 @@ void setup() { // 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 @@ -169,7 +173,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, ENABLE_LED_FEEDBACK, USE_DEFAULT_FEEDBACK_LED_PIN);// Specify send pin and enable feedback LED at default feedback LED pin // You can change send pin later with IrSender.setSendPin(); Serial.print(F("Send IR signals at pin ")); @@ -485,17 +489,14 @@ void loop() { delay(DELAY_AFTER_SEND); # endif -# if __INT_WIDTH__ < 32 - IRRawDataType tRawData[4] = { 0xB02002, 0xA010, 0x0, 0x0 }; // LSB of tRawData[0] is sent first -# endif # if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromArray(&KaseikyoProtocolConstants, &tRawData[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &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); @@ -507,18 +508,19 @@ void loop() { 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, &tRawDataPGM[0], 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); + NO_REPEATS); checkReceivedRawData(0xA010B02002); # endif delay(DELAY_AFTER_SEND); // The same with MSB first. Use bit reversed raw data of LSB first part Serial.println(F("-MSB first")); + IRRawDataType tRawData[4]; # if __INT_WIDTH__ < 32 tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first tRawData[1] = 0x805; @@ -527,7 +529,7 @@ void loop() { checkReceive(0x0B, 0x10); # else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, - NO_REPEATS); + NO_REPEATS); checkReceivedRawData(0x40040D000805); # endif @@ -579,9 +581,10 @@ void loop() { NO_REPEATS); checkReceivedArray(tRawData, 3); # else - IRRawDataType tRawData[] = { 0xAFEDCBA987654321, 0x5A }; // LSB of tRawData[0] is sent first + 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); + NO_REPEATS); checkReceivedArray(tRawData, 2); # endif delay(DELAY_AFTER_SEND); diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index dfce94271..d5f4e78cf 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -988,6 +988,15 @@ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a aProtocolConstants->Flags); } +bool IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, + uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) { + PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; + memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, + sizeof(tTemporaryPulseDistanceWidthProtocolConstants)); + + return decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset); +} + /* * Static variables for the getBiphaselevel function */ @@ -1171,6 +1180,25 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants return true; } +bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM) { +// Check header "mark" and "space" + if (!matchMark(decodedIRData.rawDataPtr->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")); +#endif + return false; + } + if (!matchSpace(decodedIRData.rawDataPtr->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")); +#endif + return false; + } + return true; +} + /* * 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. diff --git a/src/IRSend.hpp b/src/IRSend.hpp index b9a4b786e..5d7f0087c 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -597,6 +597,87 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_ } } +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) { + + // Set IR carrier frequency + 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); + if (tNumberOf32Or64BitChunks > 1) { + Serial.print(F(" Data[1]=0x")); + Serial.print(aDecodedRawDataArray[1], HEX); + } + Serial.print(F(" #=")); + Serial.println(aNumberOfBits); + Serial.flush(); +#endif + + while (tNumberOfCommands > 0) { + unsigned long tStartOfFrameMillis = millis(); + + // Header + 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 = aNumberOfBits; + tFlags = aFlags; + } else { + // intermediate data + tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; + tFlags = aFlags | 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 + sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, tDecodedRawData, + tNumberOfBitsForOneSend, tFlags); + aNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + } + + 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_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); +} + /** * 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. @@ -680,6 +761,104 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants } } +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::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, + IRRawDataType const *aDecodedRawDataPGMArray, 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(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) { + 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 + sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, + aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, + aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, + aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, tDecodedRawData, tNumberOfBitsForOneSend, tFlags); + tNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + } + + 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); + } + } + } +} + /** * Sends PulseDistance frames and repeats * @param aProtocolConstants The constants to use for sending this protocol. @@ -744,6 +923,13 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc } } } +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 PulseDistance frames and repeats. @@ -817,6 +1003,15 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr 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); +} + /** * Sends PulseDistance data with timing parameters and flag parameters. * The output always ends with a space diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 10a122444..02023a8df 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -206,8 +206,12 @@ class IRrecv { public: IRrecv(); - 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.."))); + 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.."))); void setReceivePin(uint_fast8_t aReceivePinNumber); #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) void registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)); @@ -225,7 +229,6 @@ class IRrecv { void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter); void restartAfterSend(); - bool available(); IRData* read(); // returns decoded data // write is a method of class IRsend below @@ -283,6 +286,9 @@ class IRrecv { bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset = 3); + bool decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, + uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset = 3); + bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst); @@ -354,6 +360,7 @@ 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); @@ -494,20 +501,41 @@ 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, @@ -576,7 +604,8 @@ class IRsend { void sendRC5(uint8_t aAddress, uint8_t aCommand, 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 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); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 7d4f0b114..4b2e8959f 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. @@ -228,7 +228,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 here -> initialize data */ TinyIRReceiverControl.IRRawDataBitCounter = 0; #if (TINY_RECEIVER_BITS > 16) @@ -464,7 +464,6 @@ bool initPCIInterruptForTinyReceiver() { 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 diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index f745081aa..faeaa5afd 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -5,6 +5,8 @@ * 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) */ diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index 0843331de..336d886f0 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -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), nullptr }; +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 + , (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,7 +76,7 @@ bool IRrecv::decodeBoseWave() { return false; } - if (!decodePulseDistanceWidthData(&BoseWaveProtocolConstants, BOSEWAVE_BITS)) { + if (!decodePulseDistanceWidthData_P(&BoseWaveProtocolConstants, BOSEWAVE_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("Bose: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index 0f64a0aba..bfbe45caa 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -105,9 +105,9 @@ #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), nullptr }; +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, + (DENON_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; /************************************ * Start of send and decode functions @@ -144,11 +144,11 @@ void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOf 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--; // send repeated command with a fixed space gap @@ -158,7 +158,7 @@ void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOf * always end with a normal frame * skip last delay! */ - sendPulseDistanceWidthData(&DenonProtocolConstants, tData, DENON_BITS); + sendPulseDistanceWidthData_P(&DenonProtocolConstants, tData, DENON_BITS); } @@ -179,7 +179,7 @@ bool IRrecv::decodeDenon() { } // Try to decode as Denon protocol - if (!decodePulseDistanceWidthData(&DenonProtocolConstants, DENON_BITS, 1)) { + if (!decodePulseDistanceWidthData_P(&DenonProtocolConstants, DENON_BITS, 1)) { #if defined(LOCAL_DEBUG) Serial.print(F("Denon: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index e5cee6ea3..e01f98296 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -54,18 +54,19 @@ //============================================================================== #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), -nullptr }; + 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, (FAST_REPEAT_PERIOD + / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions @@ -84,7 +85,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,11 +109,11 @@ bool IRrecv::decodeFAST() { return false; } - if (!checkHeader(&FASTProtocolConstants)) { + if (!checkHeader_P(&FASTProtocolConstants)) { return false; } - if (!decodePulseDistanceWidthData(&FASTProtocolConstants, FAST_BITS)) { + if (!decodePulseDistanceWidthData_P(&FASTProtocolConstants, FAST_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("FAST: ")); Serial.println(F("Decode failed")); @@ -123,7 +124,7 @@ bool IRrecv::decodeFAST() { 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")); diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 3c1516797..90e7ed668 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -79,8 +79,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), nullptr }; +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, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; /************************************ * Start of send and decode functions @@ -105,7 +105,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! @@ -148,11 +148,11 @@ bool IRrecv::decodeJVC() { } } else { - if (!checkHeader(&JVCProtocolConstants)) { + if (!checkHeader_P(&JVCProtocolConstants)) { return false; } - if (!decodePulseDistanceWidthData(&JVCProtocolConstants, JVC_BITS)) { + if (!decodePulseDistanceWidthData_P(&JVCProtocolConstants, JVC_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("JVC: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 01ce36c9c..9abce660c 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -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), nullptr }; +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 + , (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,12 +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 (!decodePulseDistanceWidthData_P(&KaseikyoProtocolConstants, KASEIKYO_VENDOR_ID_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("Kaseikyo: ")); Serial.println(F("Vendor ID decode failed")); @@ -243,7 +243,7 @@ bool IRrecv::decodeKaseikyo() { /* * Decode next 32 bits, 8 VendorID parity parity + 12 address (device and subdevice) + 8 command + 8 parity */ - if (!decodePulseDistanceWidthData(&KaseikyoProtocolConstants, + if (!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) diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 812b96058..ad35f8126 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -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, (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, (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() { @@ -232,7 +232,7 @@ bool IRrecv::decodeLG() { return false; } - if (!decodePulseDistanceWidthData(&LGProtocolConstants, LG_BITS)) { + if (!decodePulseDistanceWidthData_P(&LGProtocolConstants, LG_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("LG: ")); Serial.println(F("Decode failed")); @@ -284,7 +284,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) { diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 410bf8001..156bf7439 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -83,8 +83,8 @@ #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 +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), nullptr }; /************************************ diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index e16f84420..c14e5307b 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -109,7 +109,7 @@ #define MAGIQUEST_ZERO_SPACE (3 * MAGIQUEST_UNIT) // 864 // assume 110 as repeat period -struct PulseDistanceWidthProtocolConstants MagiQuestProtocolConstants = { MAGIQUEST, 38, MAGIQUEST_ZERO_MARK, MAGIQUEST_ZERO_SPACE, +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 | SUPPRESS_STOP_BIT, 110, nullptr }; //+============================================================================= @@ -131,11 +131,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,7 +165,7 @@ bool IRrecv::decodeMagiQuest() { /* * Check for 8 zero header bits */ - if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_START_BITS, 1)) { + if (!decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_START_BITS, 1)) { #if defined(LOCAL_DEBUG) Serial.print(F("MagiQuest: ")); Serial.println(F("Start bit decode failed")); @@ -184,7 +184,7 @@ bool IRrecv::decodeMagiQuest() { /* * Decode the 31 bit ID */ - if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_WAND_ID_BITS, (MAGIQUEST_START_BITS * 2) + 1)) { + if (!decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_WAND_ID_BITS, (MAGIQUEST_START_BITS * 2) + 1)) { #if defined(LOCAL_DEBUG) Serial.print(F("MagiQuest: ")); Serial.println(F("ID decode failed")); @@ -208,7 +208,7 @@ bool IRrecv::decodeMagiQuest() { /* * Decode the 9 bit Magnitude + 8 bit checksum */ - if (!decodePulseDistanceWidthData(&MagiQuestProtocolConstants, MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_CHECKSUM_BITS, + if (!decodePulseDistanceWidthData_P(&MagiQuestProtocolConstants, MAGIQUEST_MAGNITUDE_BITS + MAGIQUEST_CHECKSUM_BITS, ((MAGIQUEST_WAND_ID_BITS + MAGIQUEST_START_BITS) * 2) + 1)) { #if defined(LOCAL_DEBUG) Serial.print(F("MagiQuest: ")); diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index eb3d52983..5bf750fea 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -115,14 +115,13 @@ #define APPLE_ADDRESS 0x87EE -struct PulseDistanceWidthProtocolConstants NECProtocolConstants = - { NEC, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, - NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), - &sendNECSpecialRepeat }; +struct PulseDistanceWidthProtocolConstants const NECProtocolConstants PROGMEM = {NEC, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, + NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), + &sendNECSpecialRepeat}; // Like NEC but repeats are full frames instead of special NEC repeats -struct PulseDistanceWidthProtocolConstants NEC2ProtocolConstants = { NEC2, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, -NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; +struct PulseDistanceWidthProtocolConstants const NEC2ProtocolConstants PROGMEM = {NEC2, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, + NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; /************************************ * Start of send and decode functions @@ -181,7 +180,7 @@ uint32_t IRsend::computeNECRawDataAndChecksum(uint16_t aAddress, uint16_t aComma * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&NECProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); } /** @@ -190,7 +189,7 @@ void IRsend::sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOf * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&NECProtocolConstants, (uint32_t) aCommand << 16 | aAddress, NEC_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, (uint32_t) aCommand << 16 | aAddress, NEC_BITS, aNumberOfRepeats); } /** @@ -199,7 +198,7 @@ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumber * @param aNumberOfRepeats If < 0 then nothing is sent. */ void IRsend::sendNEC2(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&NEC2ProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NEC2ProtocolConstants, computeNECRawDataAndChecksum(aAddress, aCommand), NEC_BITS, aNumberOfRepeats); } /** @@ -220,7 +219,7 @@ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberO tRawData.UByte.MidHighByte = aCommand; tRawData.UByte.HighByte = aDeviceId; // e.g. 0xD7 - sendPulseDistanceWidth(&NECProtocolConstants, tRawData.ULong, NEC_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, tRawData.ULong, NEC_BITS, aNumberOfRepeats); } /** @@ -229,7 +228,7 @@ void IRsend::sendApple(uint8_t aDeviceId, uint8_t aCommand, int_fast8_t aNumberO * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendNECRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&NECProtocolConstants, aRawData, NEC_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, aRawData, NEC_BITS, aNumberOfRepeats); } /** @@ -278,7 +277,7 @@ bool IRrecv::decodeNEC() { } // Try to decode as NEC protocol - if (!decodePulseDistanceWidthData(&NECProtocolConstants, NEC_BITS)) { + if (!decodePulseDistanceWidthData_P(&NECProtocolConstants, NEC_BITS)) { #if defined(LOCAL_DEBUG) Serial.print(F("NEC: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index e6b24b872..20e4cc62c 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -58,11 +58,11 @@ #define DISH_ZERO_SPACE 2800 #define DISH_REPEAT_SPACE 6200 // really? -struct PulseDistanceWidthProtocolConstants DishProtocolConstants = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, +struct PulseDistanceWidthProtocolConstants const DishProtocolConstants PROGMEM = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 40, nullptr }; void IRsend::sendDish(uint16_t aData) { - sendPulseDistanceWidth(&DishProtocolConstants, aData, DISH_BITS, 4); + sendPulseDistanceWidth_P(&DishProtocolConstants, aData, DISH_BITS, 4); } //============================================================================== @@ -84,11 +84,11 @@ void IRsend::sendDish(uint16_t aData) { #define WHYNTER_ONE_SPACE 2150 #define WHYNTER_ZERO_SPACE 750 -struct PulseDistanceWidthProtocolConstants WhynterProtocolConstants = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, +struct PulseDistanceWidthProtocolConstants const WhynterProtocolConstants PROGMEM = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, nullptr }; void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) { - sendPulseDistanceWidth(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend); + sendPulseDistanceWidth_P(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend); } bool IRrecv::decodeWhynter() { @@ -96,10 +96,10 @@ bool IRrecv::decodeWhynter() { if (decodedIRData.rawlen != (2 * WHYNTER_BITS) + 4) { return false; } - if (!checkHeader(&WhynterProtocolConstants)) { + if (!checkHeader_P(&WhynterProtocolConstants)) { return false; } - if (!decodePulseDistanceWidthData(&WhynterProtocolConstants, WHYNTER_BITS)) { + if (!decodePulseDistanceWidthData_P(&WhynterProtocolConstants, WHYNTER_BITS)) { return false; } // Success diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 2ca504dab..8abc2fadf 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -102,11 +102,11 @@ #define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess // 19 byte RAM -struct PulseDistanceWidthProtocolConstants SamsungProtocolConstants = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, +struct PulseDistanceWidthProtocolConstants const SamsungProtocolConstants PROGMEM = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; -struct PulseDistanceWidthProtocolConstants SamsungLGProtocolConstants = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, +struct PulseDistanceWidthProtocolConstants const SamsungLGProtocolConstants PROGMEM = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat }; /************************************ @@ -157,7 +157,7 @@ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNu tRawData.UByte.MidHighByte = aCommand; tRawData.UByte.HighByte = ~aCommand; - sendPulseDistanceWidth(&SamsungLGProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SamsungLGProtocolConstants, tRawData.ULong, SAMSUNG_BITS, aNumberOfRepeats); } /** @@ -191,7 +191,7 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb tSendValue.UWords[1] = aCommand; } - sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } /** @@ -208,7 +208,7 @@ void IRsend::sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aC tSendValue.UBytes[2] = aCommand; tSendValue.UBytes[3] = ~aCommand; - sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } /** @@ -224,7 +224,7 @@ void IRsend::sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aComm // Send 16 command bits tSendValue.UWords[1] = aCommand; - sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SamsungProtocolConstants, tSendValue.ULong, SAMSUNG_BITS, aNumberOfRepeats); } /** * Here we send Samsung48 @@ -244,7 +244,7 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu tRawSamsungData[1] = tUpper8BitsOfCommand | (~tUpper8BitsOfCommand) << 8; tRawSamsungData[0] = tSendValue.ULong; - sendPulseDistanceWidthFromArray(&SamsungProtocolConstants, &tRawSamsungData[0], SAMSUNG48_BITS, aNumberOfRepeats); + sendPulseDistanceWidthFromArray_P(&SamsungProtocolConstants, &tRawSamsungData[0], SAMSUNG48_BITS, aNumberOfRepeats); #else LongLongUnion tSendValue; tSendValue.UWords[0] = aAddress; @@ -257,7 +257,7 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu } else { tSendValue.ULongLong = aAddress | aCommand << 16; } - sendPulseDistanceWidth(&SamsungProtocolConstants, tSendValue.ULongLong, SAMSUNG48_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SamsungProtocolConstants, tSendValue.ULongLong, SAMSUNG48_BITS, aNumberOfRepeats); #endif } @@ -278,7 +278,7 @@ bool IRrecv::decodeSamsung() { return false; } - if (!checkHeader(&SamsungProtocolConstants)) { + if (!checkHeader_P(&SamsungProtocolConstants)) { return false; } @@ -294,7 +294,7 @@ bool IRrecv::decodeSamsung() { /* * Decode first 32 bits */ - if (!decodePulseDistanceWidthData(&SamsungProtocolConstants, SAMSUNG_BITS, 3)) { + if (!decodePulseDistanceWidthData_P(&SamsungProtocolConstants, SAMSUNG_BITS, 3)) { #if defined(LOCAL_DEBUG) Serial.print(F("Samsung: ")); Serial.println(F("Decode failed")); @@ -310,7 +310,7 @@ bool IRrecv::decodeSamsung() { * Samsung48 */ // decode additional 16 bit - if (!decodePulseDistanceWidthData(&SamsungProtocolConstants, (SAMSUNG_COMMAND32_BITS - SAMSUNG_COMMAND16_BITS), + if (!decodePulseDistanceWidthData_P(&SamsungProtocolConstants, (SAMSUNG_COMMAND32_BITS - SAMSUNG_COMMAND16_BITS), 3 + (2 * SAMSUNG_BITS))) { #if defined(LOCAL_DEBUG) Serial.print(F("Samsung: ")); diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index af9e6bc58..bcb9eb9d2 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -90,7 +90,7 @@ #define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down. #define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms -struct PulseDistanceWidthProtocolConstants SonyProtocolConstants = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK, +struct PulseDistanceWidthProtocolConstants const SonyProtocolConstants PROGMEM = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ @@ -103,12 +103,12 @@ SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERI void IRsend::sendSony(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t numberOfBits) { uint32_t tData = (uint32_t) aAddress << 7 | (aCommand & 0x7F); // send 5, 8, 13 address bits LSB first - sendPulseDistanceWidth(&SonyProtocolConstants, tData, numberOfBits, aNumberOfRepeats); + sendPulseDistanceWidth_P(&SonyProtocolConstants, tData, numberOfBits, aNumberOfRepeats); } bool IRrecv::decodeSony() { - if (!checkHeader(&SonyProtocolConstants)) { + if (!checkHeader_P(&SonyProtocolConstants)) { return false; } @@ -122,7 +122,7 @@ bool IRrecv::decodeSony() { return false; } - if (!decodePulseDistanceWidthData(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3)) { + if (!decodePulseDistanceWidthData_P(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3)) { #if defined(LOCAL_DEBUG) Serial.print(F("Sony: ")); Serial.println(F("Decode failed")); diff --git a/src/ir_Template.hpp b/src/ir_Template.hpp index 82bad807a..ce1dab069 100644 --- a/src/ir_Template.hpp +++ b/src/ir_Template.hpp @@ -123,9 +123,9 @@ #define SHUZU_OTHER 1234 // Other things you may need to define // use BOSEWAVE, we have no SHUZU code -struct PulseDistanceWidthProtocolConstants ShuzuProtocolConstants = { BOSEWAVE, 38, SHUZU_HEADER_MARK, SHUZU_HEADER_SPACE, -SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SHUZU_REPEAT_PERIOD - / MICROS_IN_ONE_MILLI), nullptr }; +struct PulseDistanceWidthProtocolConstants const ShuzuProtocolConstants PROGMEM = {BOSEWAVE, 38, SHUZU_HEADER_MARK, SHUZU_HEADER_SPACE, + SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (SHUZU_REPEAT_PERIOD + / MICROS_IN_ONE_MILLI), nullptr}; /************************************ * Start of send and decode functions @@ -133,7 +133,7 @@ SHUZU_BIT_MARK, SHUZU_ONE_SPACE, SHUZU_BIT_MARK, SHUZU_ZERO_SPACE, PROTOCOL_IS_L void IRsend::sendShuzu(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth(&ShuzuProtocolConstants, (uint32_t) aCommand << 8 | aCommand, SHUZU_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&ShuzuProtocolConstants, (uint32_t) aCommand << 8 | aCommand, SHUZU_BITS, aNumberOfRepeats); } bool IRrecv::decodeShuzu() { @@ -149,12 +149,12 @@ bool IRrecv::decodeShuzu() { } // Check header - if (!checkHeader(&ShuzuProtocolConstants)) { + if (!checkHeader_P(&ShuzuProtocolConstants)) { return false; } // Decode - if (!decodePulseDistanceData(&ShuzuProtocolConstants, SHUZU_BITS)) { + if (!decodePulseDistanceData_P(&ShuzuProtocolConstants, SHUZU_BITS)) { IR_DEBUG_PRINT(F("Shuzu: ")); IR_DEBUG_PRINTLN(F("Decode failed")); return false; From ae93ec10498e5164af0e4d6be024e4f870f4e8b5 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 23 Mar 2025 19:52:11 +0100 Subject: [PATCH 079/133] bumped version to 4.4.2 --- .github/workflows/LibraryBuild.yml | 87 +++++++++++----------- changelog.md | 5 +- examples/SendDemo/SendDemo.ino | 41 +++++----- examples/SimpleReceiver/SimpleReceiver.ino | 2 +- examples/UnitTest/UnitTest.ino | 78 +++++++++---------- library.json | 2 +- library.properties | 4 +- src/IRProtocol.hpp | 8 ++ src/IRReceive.hpp | 4 +- src/IRSend.hpp | 27 +++++-- src/IRVersion.h | 6 +- src/IRremote.h | 4 +- src/IRremote.hpp | 2 + src/TinyIRReceiver.hpp | 10 +-- src/ir_JVC.hpp | 3 +- src/ir_MagiQuest.hpp | 1 - src/ir_Pronto.hpp | 2 + src/ir_RC5_RC6.hpp | 1 + src/ir_Samsung.hpp | 22 ++++-- 19 files changed, 174 insertions(+), 135 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 600535094..93aee1426 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -47,7 +47,7 @@ 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 @@ -61,13 +61,13 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect -# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll -# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled -# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll + - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro -# - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal -# - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal + - 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 @@ -86,11 +86,11 @@ jobs: ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK 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 + All: -DEBUG -DTRACE - arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM build-properties: # the flags were put in compiler.cpp.extra_flags @@ -128,7 +128,7 @@ jobs: 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 @@ -184,43 +184,45 @@ jobs: # # megaTinyCore # -# - 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 -# build-properties: # the flags were put in compiler.cpp.extra_flags -# IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 - -# - 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 + build-properties: # the flags were put in compiler.cpp.extra_flags + IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 + + - 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 # # 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,SimpleReceiverForHashCodes.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,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 + - 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 @@ -284,6 +286,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 diff --git a/changelog.md b/changelog.md index 4372d417e..0ab56fa17 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,9 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - 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. @@ -310,7 +313,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. diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 724963f67..c918aa3a1 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -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 @@ -42,8 +42,9 @@ //#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 - +#if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85 +#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory +#endif //#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below #include @@ -149,7 +150,7 @@ void loop() { delay(DELAY_AFTER_SEND); if (sRepeats == 0) { -#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. +#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 */ @@ -200,11 +201,11 @@ void loop() { Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); Serial.flush(); -#if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant -#else +# else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant -#endif +# endif delay(DELAY_AFTER_SEND); @@ -214,56 +215,55 @@ void loop() { Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance")); Serial.println(F(" LSB first")); Serial.flush(); -#if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawDataPGM[0], 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); -#else +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); -#endif +# endif delay(DELAY_AFTER_SEND); // The same with MSB first. Use bit reversed raw data of LSB first part Serial.println(F(" MSB first")); IRRawDataType tRawData[4]; -#if __INT_WIDTH__ < 32 +# 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 +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS); -#endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); 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 +# 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 +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); 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 +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); -#endif +# endif delay(DELAY_AFTER_SEND); -#endif Serial.println(F("Send ASCII 7 bit PulseDistanceWidth LSB first")); Serial.flush(); @@ -276,6 +276,7 @@ void loop() { 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.flush(); diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 6d4d40a65..95eaee8c7 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -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 diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index fe9961079..afdbf4bc7 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 @@ -437,7 +437,9 @@ void loop() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. if (sAddress == 0xFFF1) { -# if FLASHEND >= 0x7FFF && ((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 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. + IRRawDataType tRawData[4]; + /* * Send constant values only once in this demo */ @@ -487,18 +489,17 @@ void loop() { IrSender.sendNECMSB(0x40802CD3, 32, false); checkReceive(0x0102, 0x34); delay(DELAY_AFTER_SEND); -# endif -# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceivedRawData(0xA010B02002); -# endif +# endif delay(DELAY_AFTER_SEND); /* @@ -507,61 +508,60 @@ void loop() { Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance")); Serial.println(F("-LSB first")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawDataPGM[0], 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0xA010B02002); -# endif +# endif delay(DELAY_AFTER_SEND); // The same with MSB first. Use bit reversed raw data of LSB first part Serial.println(F("-MSB first")); - IRRawDataType tRawData[4]; -# if __INT_WIDTH__ < 32 +# 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); checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0x40040D000805); -# endif +# endif delay(DELAY_AFTER_SEND); -# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) -# if defined(DECODE_DISTANCE_WIDTH) -# if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) +# 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.flush(); -# if __INT_WIDTH__ < 32 +# 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); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0x43D8613CBC3B); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 52 bit PulseDistanceWidth 0x43D8613C and 0x3BC3B MSB first")); 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_MSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0x123456789ABC, 52, PROTOCOL_IS_MSB_FIRST, 0, 0); checkReceivedRawData(0x123456789ABC); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first")); Serial.flush(); @@ -570,49 +570,49 @@ void loop() { checkReceivedRawData(0x43D8613C); delay(DELAY_AFTER_SEND); -# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) +# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) Serial.println(F("Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first")); 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); checkReceivedArray(tRawData, 3); -# else +# 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); checkReceivedArray(tRawData, 2); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first")); 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 +# if __INT_WIDTH__ < 32 tRawData[1] = 0xDCBA9; IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 300, 600, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 300, 600, 600, 300, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0xDCBA987654321); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 tRawData[2] = ~tRawData[0]; tRawData[3] = ~tRawData[1]; IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0xDCBA987654321); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first")); @@ -635,16 +635,18 @@ void loop() { checkReceivedRawData(0x87654321); delay(DELAY_AFTER_SEND); -# endif // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) -# endif // defined(DECODE_DISTANCE_WIDTH) +# endif // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) +# endif // defined(DECODE_DISTANCE_WIDTH) +# endif // if FLASHEND >= 0x7FFF ... # if defined(DECODE_MAGIQUEST) Serial.println(F("Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first")); 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 diff --git a/library.json b/library.json index dbfb3f3ef..c0666baa1 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.4.1", + "version": "4.4.2", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index e42b826e8..40e043e2a 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.4.1 +version=4.4.2 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, 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/src/IRProtocol.hpp b/src/IRProtocol.hpp index 9153be564..bed8fa7a6 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -150,6 +150,10 @@ namespace PrintULL { # endif #endif +/** @} + * \addtogroup Print Print functions + * @{ + */ /** * 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. @@ -267,6 +271,10 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { } } +/** @} + * \addtogroup Utils Utility functions + * @{ + */ /********************************************************************************************************************** * Function to bit reverse OLD MSB values of e.g. NEC. **********************************************************************************************************************/ diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index d5f4e78cf..ab4095f61 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1184,14 +1184,14 @@ bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolC // Check header "mark" and "space" if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex)); + Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header mark length is wrong")); #endif return false; } if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex)); + Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header space length is wrong")); #endif return false; diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 5d7f0087c..365c17c0a 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -611,10 +611,10 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint #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); @@ -798,10 +798,10 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta #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); @@ -1206,7 +1206,12 @@ void IRsend::mark(uint16_t aMarkMicros) { # 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. @@ -1221,7 +1226,11 @@ void IRsend::mark(uint16_t aMarkMicros) { # 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. @@ -1411,7 +1420,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 d4dd23f3b..acbafa22c 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,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.4.1" +#define VERSION_IRREMOTE "4.4.2" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 4 -#define VERSION_IRREMOTE_PATCH 1 +#define VERSION_IRREMOTE_PATCH 2 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremote.h b/src/IRremote.h index 3cc42969c..73cae0385 100644 --- a/src/IRremote.h +++ b/src/IRremote.h @@ -11,10 +11,10 @@ #warning It seems, that you are using an old version 2.0 code / example. #warning This version is no longer supported! -#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 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?tab=readme-ov-file#examples-for-this-library +#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. /********************************************************************************************************************** diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 43f3d5d76..826e8044e 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -259,7 +259,9 @@ * 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 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 4b2e8959f..c0d29661d 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -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 @@ -94,10 +94,8 @@ #endif #if defined(TRACE) -#define LOCAL_TRACE #define LOCAL_TRACE_STATE_MACHINE #else -//#define LOCAL_TRACE // This enables trace output only for this file //#define LOCAL_TRACE_STATE_MACHINE // to see the state of the ISR (Interrupt Service Routine) state machine #endif @@ -153,9 +151,7 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; */ 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. @@ -211,7 +207,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) diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 90e7ed668..ef69a5986 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -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 diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index c14e5307b..ccd214f89 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -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 diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 620829ed5..5fbad18c5 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -2,6 +2,8 @@ * @file ir_Pronto.hpp * @brief In this file, the functions IRrecv::compensateAndPrintPronto and IRsend::sendPronto are defined. * + * Pronto is the standard for the professional audio and video hardware market. + * * See http://www.harctoolbox.org/Glossary.html#ProntoSemantics * Pronto database http://www.remotecentral.com/search.htm * diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 35506699d..b8eebb57a 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -70,6 +70,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 // // see: https://www.sbprojects.net/knowledge/ir/rc5.php // https://en.wikipedia.org/wiki/Manchester_code +// https://en.wikipedia.org/wiki/RC-5 // https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended // mark->space => 0 // space->mark => 1 diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 8abc2fadf..976e88078 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -102,13 +102,13 @@ #define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess // 19 byte RAM -struct PulseDistanceWidthProtocolConstants const SamsungProtocolConstants PROGMEM = { SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, -SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, - (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; +struct PulseDistanceWidthProtocolConstants const SamsungProtocolConstants PROGMEM = {SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, + SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, + (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; -struct PulseDistanceWidthProtocolConstants const SamsungLGProtocolConstants PROGMEM = { SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, -SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, - (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat }; +struct PulseDistanceWidthProtocolConstants const SamsungLGProtocolConstants PROGMEM = {SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, + SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, + (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat}; /************************************ * Start of send and decode functions ************************************/ @@ -143,6 +143,7 @@ void sendSamsungLGSpecialRepeat() { /* * Sent e.g. by an LG 6711R1P071A remote + * @param aAddress 16 bit address. If < 0x100, i.e. only 8 bit, then a (standard) 16 bit address <8_bit_address><8_bit_address> is generated. * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent */ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { @@ -154,6 +155,9 @@ void IRsend::sendSamsungLG(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNu // send 16 bit address and 8 command bits and then 8 inverted command bits LSB first LongUnion tRawData; tRawData.UWord.LowWord = aAddress; + if (aAddress < 0x100) { // This disables the sending of an (non standard?) 16 bit address with upper byte = 0 like 0x0014. + tRawData.UByte.MidLowByte = aAddress; // here we have 8 bit address which must be duplicated + } tRawData.UByte.MidHighByte = aCommand; tRawData.UByte.HighByte = ~aCommand; @@ -349,11 +353,15 @@ bool IRrecv::decodeSamsung() { if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { // 8 bit command protocol -> assume 8 bit address decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit - decodedIRData.address = tValue.UByte.LowByte; // assume LowByte == MidLowByte + } + + if (tValue.UByte.MidLowByte == tValue.UByte.LowByte) { + decodedIRData.address = tValue.UByte.LowByte; // assume LowByte == MidLowByte as seen for a LG HX906 A/V Receive E8172C2C } else { // 16 bit command protocol, address is filled above with the 16 bit value decodedIRData.command = tValue.UWord.HighWord; // first 16 bit } + decodedIRData.numberOfBits = SAMSUNG_BITS; decodedIRData.protocol = SAMSUNG; } From c0d4c081e0a3e423701e4568d39e12b6cca61bdd Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 21 Apr 2025 09:22:08 +0200 Subject: [PATCH 080/133] Extended NO_LED_FEEDBACK_CODE to NO_LED_RECEIVE_FEEDBACK_CODE and NO_LED_SEND_FEEDBACK_CODE, C3 pin assignment --- README.md | 6 +- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 4 +- examples/ControlRelay/PinDefinitionsAndMore.h | 4 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- examples/MicroGirs/PinDefinitionsAndMore.h | 4 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 4 +- examples/ReceiveDemo/ReceiveDemo.ino | 32 +++++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- .../SendAndReceive/PinDefinitionsAndMore.h | 4 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 4 +- examples/SendDemo/PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 4 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 4 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- .../PinDefinitionsAndMore.h | 4 +- examples/SimpleSender/PinDefinitionsAndMore.h | 4 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 4 +- examples/TinySender/PinDefinitionsAndMore.h | 4 +- examples/UnitTest/PinDefinitionsAndMore.h | 4 +- src/IRReceive.hpp | 10 +- src/IRSend.hpp | 36 +++---- src/IRremote.hpp | 13 ++- src/TinyIR.h | 13 +++ src/TinyIRReceiver.hpp | 28 ++++-- src/TinyIRSender.hpp | 96 ++++++++++++++++--- 32 files changed, 226 insertions(+), 104 deletions(-) diff --git a/README.md b/README.md index 256003fcd..d630db6e6 100644 --- a/README.md +++ b/README.md @@ -869,6 +869,8 @@ Modify them by enabling / disabling them, or change the values if applicable. | `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | | `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | +| `NO_LED_RECEIVE_FEEDBACK_CODE` | disabled | Disables the LED feedback code for receive. Saves around 100 bytes program memory for receiving and halving the receiver ISR (Interrupt Service Routine) processing time. | +| `NO_LED_SEND_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send. Saves around 500 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. | @@ -879,7 +881,9 @@ These next macros for **TinyIRReceiver** must be defined in your program before |-|-:|-| | `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. | +| `NO_LED_FEEDBACK_CODE` | disabled | Disables the feedback LED codefor 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 addres and command parity checks. Saves 48 bytes program memory. | | `USE_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | | `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index f66a10a70..e7aa1eb7b 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -114,6 +114,11 @@ #else #define DEBUG_BUTTON_PIN 6 #endif +#if defined(ESP32) +# 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(); @@ -121,13 +126,15 @@ 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); + Serial.begin(9600); - #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) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) || (defined(ESP32) && defined(ARDUINO_USB_MODE)) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif @@ -159,13 +166,15 @@ void setup() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. Serial.println(); +# if defined(DEBUG_BUTTON_PIN) Serial.print(F("If you connect debug pin ")); -# if defined(APPLICATION_PIN_STRING) +# if defined(APPLICATION_PIN_STRING) Serial.print(APPLICATION_PIN_STRING); -# else +# else Serial.print(DEBUG_BUTTON_PIN); -# endif +# endif Serial.println(F(" to ground, raw data is always printed and tone is disabled")); +# endif // infos for receive Serial.print(RECORD_GAP_MICROS); @@ -202,7 +211,10 @@ void loop() { */ 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. @@ -215,7 +227,11 @@ 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")); diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 5e9328296..b13414f56 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -186,8 +186,8 @@ #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 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index ab4095f61..1c6ab4fb5 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -71,7 +71,7 @@ unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR wi IRrecv::IRrecv() { decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc. setReceivePin(0); -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); #endif } @@ -79,7 +79,7 @@ IRrecv::IRrecv() { IRrecv::IRrecv(uint_fast8_t aReceivePin) { decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc. setReceivePin(aReceivePin); -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); #endif } @@ -92,7 +92,7 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin) { IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc. setReceivePin(aReceivePin); -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) setLEDFeedback(aFeedbackLEDPin, DO_NOT_ENABLE_LED_FEEDBACK); #else (void) aFeedbackLEDPin; @@ -253,7 +253,7 @@ void IRReceiveTimerInterruptHandler() { } } -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_RECEIVE) { setFeedbackLED(tIRInputLevel == INPUT_MARK); } @@ -293,7 +293,7 @@ ISR() void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) { setReceivePin(aReceivePin); -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if (aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE; diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 365c17c0a..f6c158df8 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -69,7 +69,7 @@ IRsend::IRsend() { // @suppress("Class members should be properly initialized") sendPin = 0; #endif -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_SEND_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); #endif } @@ -80,7 +80,7 @@ IRsend::IRsend() { // @suppress("Class members should be properly initialized") * Simple start with defaults - LED feedback enabled! Used if IR_SEND_PIN is defined. Saves program memory. */ void IRsend::begin(){ -# if !defined(NO_LED_FEEDBACK_CODE) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND); # endif #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) @@ -94,7 +94,7 @@ void IRsend::begin(){ * @param aFeedbackLEDPin If 0 / USE_DEFAULT_FEEDBACK_LED_PIN, 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) +#if !defined(NO_LED_SEND_FEEDBACK_CODE) uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if(aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND; @@ -109,7 +109,7 @@ void IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t 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) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); # endif } @@ -120,7 +120,7 @@ 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) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) setLEDFeedback(USE_DEFAULT_FEEDBACK_LED_PIN, LED_FEEDBACK_ENABLED_FOR_SEND); # endif } @@ -142,7 +142,7 @@ void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t sendPin = aSendPin; #endif -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_SEND_FEEDBACK_CODE) uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK; if (aEnableLEDFeedback) { tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_SEND; @@ -1142,7 +1142,7 @@ 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 !defined(NO_LED_SEND_FEEDBACK_CODE) if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(true); } @@ -1173,7 +1173,7 @@ void IRsend::mark(uint16_t aMarkMicros) { customDelayMicroseconds(aMarkMicros); IRLedOff(); -# if !defined(NO_LED_FEEDBACK_CODE) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } @@ -1187,7 +1187,7 @@ void IRsend::mark(uint16_t aMarkMicros) { unsigned long tStartMicros = micros(); unsigned long tNextPeriodEnding = tStartMicros; unsigned long tMicros; -# if !defined(NO_LED_FEEDBACK_CODE) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) bool FeedbackLedIsActive = false; # endif @@ -1238,7 +1238,7 @@ void IRsend::mark(uint16_t aMarkMicros) { */ interrupts(); -# if !defined(NO_LED_FEEDBACK_CODE) +# if !defined(NO_LED_SEND_FEEDBACK_CODE) /* * Delayed call of setFeedbackLED() to get better startup timing, especially required for consecutive marks */ @@ -1253,8 +1253,8 @@ void IRsend::mark(uint16_t aMarkMicros) { * 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. + * Minimal pause duration is 5.2 us with NO_LED_SEND_FEEDBACK_CODE enabled + * and 8.1 us with NO_LED_SEND_FEEDBACK_CODE disabled. */ tNextPeriodEnding += 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 @@ -1268,8 +1268,8 @@ 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. + * The rest of the loop takes 1.2 us with NO_LED_SEND_FEEDBACK_CODE enabled + * and 3 us with NO_LED_SEND_FEEDBACK_CODE disabled. */ #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles @@ -1282,7 +1282,7 @@ void IRsend::mark(uint16_t aMarkMicros) { #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 !defined(NO_LED_SEND_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); @@ -1293,7 +1293,7 @@ void IRsend::mark(uint16_t aMarkMicros) { 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 !defined(NO_LED_SEND_FEEDBACK_CODE) if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } @@ -1338,7 +1338,7 @@ void IRsend::IRLedOff() { # endif #endif -#if !defined(NO_LED_FEEDBACK_CODE) +#if !defined(NO_LED_SEND_FEEDBACK_CODE) if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_SEND) { setFeedbackLED(false); } @@ -1387,7 +1387,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) diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 826e8044e..fdeeb8350 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 @@ -56,6 +56,8 @@ * - 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. @@ -254,6 +256,15 @@ #define MICROS_IN_ONE_SECOND 1000000L #define MICROS_IN_ONE_MILLI 1000L +#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 + #include "IRremoteInt.h" /* * We always use digitalWriteFast() and digitalReadFast() functions to have a consistent mapping for pins. diff --git a/src/TinyIR.h b/src/TinyIR.h index ccc9ba410..8e29871e3 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -263,6 +263,19 @@ 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(). diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index c0d29661d..af66d3c84 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -56,9 +56,11 @@ * * - 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. @@ -78,6 +80,10 @@ //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. + +//#define 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" @@ -107,8 +113,6 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; /* * Set input pin and output pin definitions etc. */ -//#define IR_RECEIVE_PIN 2 -//#define IR_FEEDBACK_LED_PIN LED_BUILTIN #if defined(IR_INPUT_PIN) #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN" #define IR_RECEIVE_PIN IR_INPUT_PIN @@ -127,9 +131,6 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; # endif #endif -#if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN) -#define IR_FEEDBACK_LED_PIN LED_BUILTIN -#endif #if !( \ (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \ @@ -170,8 +171,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(NO_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 /* @@ -452,8 +457,11 @@ bool isIRReceiverAttachedForTinyReceiver() { bool initPCIInterruptForTinyReceiver() { pinModeFast(IR_RECEIVE_PIN, INPUT); -#if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#if !defined(NO_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(); } diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 86f308ac1..be0d07ef7 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 @@ -53,6 +53,8 @@ #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" @@ -114,6 +116,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 +132,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 +143,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 +164,14 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast } } } +#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, HIGH); +# else + digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); +# endif +#endif } /* @@ -168,6 +187,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(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(); @@ -175,10 +203,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 +229,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 +250,14 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ } } } +#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, HIGH); +# else + digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); +# endif +#endif } /* @@ -234,6 +270,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(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(); @@ -241,10 +286,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 +303,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 +324,14 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin } } } +#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, HIGH); +# else + digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); +# endif +#endif } /* @@ -294,6 +347,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(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(); @@ -337,6 +399,14 @@ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats } } } +#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, HIGH); +# else + digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); +# endif +#endif } /** @}*/ From 54ebbbdd9a1f91d2db6c0c74fb346695e63a93c7 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 5 May 2025 10:55:39 +0200 Subject: [PATCH 081/133] Documentation --- Contributors.md | 1 + README.md | 17 +++--- examples/AllProtocolsOnLCD/ADCUtils.hpp | 3 + .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 7 ++- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 30 ++++----- examples/ControlRelay/PinDefinitionsAndMore.h | 30 ++++----- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 30 ++++----- .../IRremoteExtensionClass.cpp | 2 +- .../IRremoteExtensionClass.h | 2 +- .../PinDefinitionsAndMore.h | 30 ++++----- examples/MicroGirs/PinDefinitionsAndMore.h | 30 ++++----- .../ReceiveAndSend/PinDefinitionsAndMore.h | 30 ++++----- examples/ReceiveAndSend/ReceiveAndSend.ino | 5 +- .../PinDefinitionsAndMore.h | 30 ++++----- .../PinDefinitionsAndMore.h | 30 ++++----- examples/ReceiveDemo/PinDefinitionsAndMore.h | 30 ++++----- examples/ReceiveDemo/ReceiveDemo.ino | 5 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 30 ++++----- examples/ReceiveDump/ReceiveDump.ino | 8 ++- .../PinDefinitionsAndMore.h | 30 ++++----- .../ReceiveOneAndSendMultiple.ino | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 30 ++++----- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 30 ++++----- examples/SendDemo/PinDefinitionsAndMore.h | 30 ++++----- examples/SendDemo/SendDemo.ino | 21 ++++--- .../PinDefinitionsAndMore.h | 30 ++++----- .../SendProntoDemo/PinDefinitionsAndMore.h | 30 ++++----- examples/SendRawDemo/PinDefinitionsAndMore.h | 30 ++++----- .../SimpleReceiver/PinDefinitionsAndMore.h | 30 ++++----- .../PinDefinitionsAndMore.h | 30 ++++----- .../PinDefinitionsAndMore.h | 30 ++++----- examples/SimpleSender/PinDefinitionsAndMore.h | 30 ++++----- examples/TinyReceiver/PinDefinitionsAndMore.h | 30 ++++----- examples/TinySender/PinDefinitionsAndMore.h | 30 ++++----- examples/UnitTest/PinDefinitionsAndMore.h | 30 ++++----- examples/UnitTest/UnitTest.ino | 22 ++++--- src/IRProtocol.h | 2 +- src/IRSend.hpp | 2 +- src/IRremote.hpp | 16 ++--- src/IRremoteInt.h | 2 +- src/ir_DistanceWidthProtocol.hpp | 2 +- src/ir_LG.hpp | 2 +- src/ir_MagiQuest.hpp | 2 +- src/ir_NEC.hpp | 2 +- src/ir_Pronto.hpp | 61 ++++++++++--------- src/ir_RC5_RC6.hpp | 2 +- src/ir_Samsung.hpp | 2 +- src/private/IRTimer.hpp | 7 ++- 48 files changed, 498 insertions(+), 419 deletions(-) diff --git a/Contributors.md b/Contributors.md index 40c040464..f016310a7 100644 --- a/Contributors.md +++ b/Contributors.md @@ -32,5 +32,6 @@ These are the active contributors of this project that you may contact if there - [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. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/README.md b/README.md index d630db6e6..ab0b220b8 100644 --- a/README.md +++ b/README.md @@ -592,7 +592,7 @@ which has very **small code size of 500 bytes and does NOT require any timer**. 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 +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). @@ -729,7 +729,7 @@ For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Ardu # 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 @@ -763,7 +763,8 @@ By connecting debug pin to ground, you can force printing of the raw values for 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. +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 Sends all available protocols at least once. @@ -861,7 +862,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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 gereration for each pin without using a shared resource (timer). | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | | `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | @@ -914,10 +915,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`. @@ -1110,6 +1112,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) @@ -1131,4 +1134,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/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 8d0e5e799..57a30a54c 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -32,6 +32,9 @@ #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 diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 36c5648bb..e381293da 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 @@ -61,8 +61,9 @@ //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active // 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. diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 ef95f8fe0..8121e115f 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 diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.h b/examples/IRremoteExtensionTest/IRremoteExtensionClass.h index 73e8c5f69..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 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 591579d85..352200211 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -86,8 +86,9 @@ //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition // 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. diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 e7aa1eb7b..44fa78e69 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -97,8 +97,9 @@ //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active //#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, -// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. -//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity. +// 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! diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 b01010626..d1921efb4 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 @@ -44,14 +44,15 @@ /* * 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. @@ -90,6 +91,7 @@ void setup() { Serial.print(RECORD_GAP_MICROS); Serial.println(F(" us is the (minimum) gap, after which the start of a new IR packet is assumed")); Serial.print(MARK_EXCESS_MICROS); + Serial.println(F(" us are subtracted from all marks and added to all spaces for decoding")); Serial.println(); Serial.println(F("Because of the verbose output (>200 ms at 115200 baud), repeats are not dumped correctly!")); Serial.println(); diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 e11a0875e..fd2a89326 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 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 c918aa3a1..79fd85e20 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -52,7 +52,14 @@ #define DELAY_AFTER_LOOP 5000 #if __INT_WIDTH__ < 32 - IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first +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 void setup() { @@ -199,10 +206,10 @@ void loop() { IrSender.sendNECMSB(0x40802CD3, 32, false); delay(DELAY_AFTER_SEND); - 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")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + 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 @@ -212,11 +219,11 @@ 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")); Serial.println(F(" LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawDataPGM[0], 48, + 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, @@ -395,14 +402,14 @@ void loop() { Serial.println(F("Send next protocols with IrSender.write")); Serial.flush(); - IRSendData.protocol = JVC;// switch protocol + IRSendData.protocol = JVC; // switch protocol Serial.print(F("Send ")); Serial.println(getProtocolString(IRSendData.protocol)); Serial.flush(); IrSender.write(&IRSendData, sRepeats); delay(DELAY_AFTER_SEND); - IRSendData.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 b13414f56..907e2a641 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index b13414f56..907e2a641 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -51,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. @@ -61,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 @@ -90,7 +92,7 @@ #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 @@ -101,21 +103,21 @@ #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 @@ -221,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" @@ -263,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 @@ -326,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 afdbf4bc7..07af75697 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -51,10 +51,12 @@ #if FLASHEND <= 0x7FFF // For 32k flash or less, like ATmega328 #define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory #endif -// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER -// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 142. -//#define MARK_EXCESS_MICROS 20 // Adapt it to your IR receiver module. 40 is taken for the cheap VS1838 module her, since we have high intensity. + +// MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, +// to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135. +// 20 is taken as default if not otherwise specified / defined. +//#define MARK_EXCESS_MICROS 40 // 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. @@ -120,7 +122,9 @@ volatile bool sDataJustReceived = false; void ReceiveCompleteCallbackHandler(); #if __INT_WIDTH__ < 32 -IRRawDataType const tRawDataPGM[4] PROGMEM = { 0xB02002, 0xA010, 0x0, 0x0 }; // LSB of tRawData[0] is sent first +//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 void setup() { @@ -491,10 +495,10 @@ void loop() { delay(DELAY_AFTER_SEND); # 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")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, &tRawDataPGM[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_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant @@ -505,12 +509,12 @@ 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")); Serial.println(F("-LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, &tRawDataPGM[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, diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 2d7654767..8f1445891 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 diff --git a/src/IRSend.hpp b/src/IRSend.hpp index f6c158df8..a2fafff19 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 diff --git a/src/IRremote.hpp b/src/IRremote.hpp index fdeeb8350..0a416a938 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -134,21 +134,23 @@ ****************************************************/ /** * 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. + * 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. * * The right value is critical for IR codes using short pulses like Denon / Sharp / Lego * * Observed values: - * Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level. - * VS1838 Mark Excess -50 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 " +// 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 #endif diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 02023a8df..8e50048e8 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 diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index bea846768..dfbe12440 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 diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index ad35f8126..0eacdb549 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 diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index ccd214f89..735995263 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 diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 5bf750fea..5ebcc878a 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 diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 5fbad18c5..e07c0b50a 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -12,7 +12,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020 Bengt Martensson + * Copyright (c) 2020-2025 Bengt Martensson, 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 @@ -101,7 +101,7 @@ void IRsend::sendPronto(const uint16_t *data, uint16_t length, int_fast8_t aNumb uint16_t durations[intros + repeats]; for (uint16_t i = 0; i < intros + repeats; i++) { uint32_t duration = ((uint32_t) data[i + numbersInPreamble]) * timebase; - durations[i] = (uint16_t) ((duration <= UINT16_MAX) ? duration : UINT16_MAX); + durations[i] = (uint16_t)((duration <= UINT16_MAX) ? duration : UINT16_MAX); } /* @@ -211,24 +211,25 @@ static uint16_t toFrequencyCode(uint16_t frequency) { return referenceFrequency / effectiveFrequency(frequency); } -static char hexDigit(uint16_t x) { +static char DigitToHex(uint8_t x) { return (char) (x <= 9 ? ('0' + x) : ('A' + (x - 10))); } -static void dumpDigit(Print *aSerial, uint16_t number) { - aSerial->print(hexDigit(number)); +static void dumpDigitHex(Print *aSerial, uint8_t number) { + aSerial->print(DigitToHex(number)); } -static void dumpNumber(Print *aSerial, uint16_t number) { +static void dumpNumberHex(Print *aSerial, uint16_t number) { + // Loop through all 4 nibbles for (uint16_t i = 0; i < digitsInProntoNumber; i++) { uint16_t shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i); - dumpDigit(aSerial, (number >> shifts) & hexMask); + dumpDigitHex(aSerial, (number >> shifts) & hexMask); } aSerial->print(' '); } -static void dumpDuration(Print *aSerial, uint32_t duration, uint16_t timebase) { - dumpNumber(aSerial, (duration + timebase / 2) / timebase); +static void dumpDurationHex(Print *aSerial, uint32_t duration, uint16_t timebase) { + dumpNumberHex(aSerial, (duration + timebase / 2) / timebase); } /* @@ -243,26 +244,27 @@ static void compensateAndDumpSequence(Print *aSerial, const volatile IRRawbufTyp } else { tDuration += getMarkExcessMicros(); } - dumpDuration(aSerial, tDuration, timebase); + dumpDurationHex(aSerial, tDuration, timebase); } // append a gap - dumpDuration(aSerial, PRONTO_DEFAULT_GAP, timebase); + dumpDurationHex(aSerial, PRONTO_DEFAULT_GAP, timebase); } /** * Print the result (second argument) as Pronto Hex on the Print supplied as argument. * Used in the ReceiveDump example. + * Do not print repeat sequence data. * @param aSerial The Print object on which to write, for Arduino you can use &Serial. * @param aFrequencyHertz Modulation frequency in Hz. Often 38000Hz. */ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFrequencyHertz) { - aSerial->println(F("Pronto Hex as string")); + aSerial->println(F("Pronto Hex as string without repeat sequence")); aSerial->print(F("char prontoData[] = \"")); - dumpNumber(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken); - dumpNumber(aSerial, toFrequencyCode(aFrequencyHertz)); - dumpNumber(aSerial, (decodedIRData.rawlen + 1) / 2); - dumpNumber(aSerial, 0); + dumpNumberHex(aSerial, aFrequencyHertz > 0 ? learnedToken : learnedNonModulatedToken); + dumpNumberHex(aSerial, toFrequencyCode(aFrequencyHertz)); + dumpNumberHex(aSerial, (decodedIRData.rawlen + 1) / 2); + dumpNumberHex(aSerial, 0); // no repeat data uint16_t timebase = toTimebase(aFrequencyHertz); compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space aSerial->println(F("\";")); @@ -273,18 +275,18 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFreque * and can lead to resource problems especially on small processors like AVR's */ -static bool dumpDigit(String *aString, uint16_t number) { - aString->concat(hexDigit(number)); +static bool dumpDigitHex(String *aString, uint8_t number) { + aString->concat(DigitToHex(number)); return number; } -static size_t dumpNumber(String *aString, uint16_t number) { +static size_t dumpNumberHex(String *aString, uint16_t number) { size_t size = 0; for (uint16_t i = 0; i < digitsInProntoNumber; i++) { uint16_t shifts = bitsInHexadecimal * (digitsInProntoNumber - 1 - i); - size += dumpDigit(aString, (number >> shifts) & hexMask); + size += dumpDigitHex(aString, (number >> shifts) & hexMask); } aString->concat(' '); size++; @@ -295,8 +297,8 @@ static size_t dumpNumber(String *aString, uint16_t number) { /* * Compensate received values by MARK_EXCESS_MICROS, like it is done for decoding! */ -static size_t dumpDuration(String *aString, uint32_t duration, uint16_t timebase) { - return dumpNumber(aString, (duration + timebase / 2) / timebase); +static size_t dumpDurationHex(String *aString, uint32_t duration, uint16_t timebase) { + return dumpNumberHex(aString, (duration + timebase / 2) / timebase); } static size_t compensateAndDumpSequence(String *aString, const volatile IRRawbufType *data, size_t length, uint16_t timebase) { @@ -311,11 +313,11 @@ static size_t compensateAndDumpSequence(String *aString, const volatile IRRawbuf } else { tDuration += getMarkExcessMicros(); } - size += dumpDuration(aString, tDuration, timebase); + size += dumpDurationHex(aString, tDuration, timebase); } // append minimum gap - size += dumpDuration(aString, PRONTO_DEFAULT_GAP, timebase); + size += dumpDurationHex(aString, PRONTO_DEFAULT_GAP, timebase); return size; } @@ -329,12 +331,11 @@ size_t IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) { size_t size = 0; uint16_t timebase = toTimebase(frequency); - size += dumpNumber(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken); - size += dumpNumber(aString, toFrequencyCode(frequency)); - size += dumpNumber(aString, (decodedIRData.rawlen + 1) / 2); - size += dumpNumber(aString, 0); - size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, - timebase); // skip leading space + size += dumpNumberHex(aString, frequency > 0 ? learnedToken : learnedNonModulatedToken); + size += dumpNumberHex(aString, toFrequencyCode(frequency)); + size += dumpNumberHex(aString, (decodedIRData.rawlen + 1) / 2); + size += dumpNumberHex(aString, 0); + size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space return size; } diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index b8eebb57a..d97f11b40 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -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 diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 976e88078..58b285df6 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.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 diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 872c4eddf..2e90423d2 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -507,7 +507,12 @@ void timerConfigForReceive() { #define IR_SEND_PIN 14 // MightyCore, MegaCore # else -#define IR_SEND_PIN 3 // Arduino Duemilanove, Diecimila, LilyPad, etc +/* + * Using pin 11 / PB3 / OC2A for this purpose is NOT possible, since we need a PWM with a selectable frequency. + * This is only possible by using Phase Correct with Top as OCR2A. + * Thus the OCR2A register cannot be used for comparing for channel A and TOP with OCR2B is not supported by Hardware :-(. + */ +#define IR_SEND_PIN 3 // Arduino Uno Pin PD3, Duemilanove, Diecimila, LilyPad, etc # endif // defined(CORE_OC2B_PIN) void enableSendPWMByTimer() { From 1ffaf9422f498a3c965e3805971a322321f0bd22 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 26 May 2025 18:09:58 +0200 Subject: [PATCH 082/133] Closes #1301 - Backward compatibility bug for printIRResultShort(3 params) --- src/IRReceive.hpp | 5 +++++ src/IRremoteInt.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 1c6ab4fb5..bf13923ca 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1428,6 +1428,11 @@ void printActiveIRProtocols(Print *aSerial) { * 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) { // call no class function with same name ::printIRResultShort(aSerial, &decodedIRData); diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 8e50048e8..17ea1f663 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -261,6 +261,8 @@ class IRrecv { /* * Next 4 functions are also available as non member functions */ + bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) + __attribute__ ((deprecated ("Remove second parameter, it is not supported any more! Third one was true by default."))); bool printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros = true); void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo); void printIRSendUsage(Print *aSerial); From 5f347050f29a40f25b230d9ba58689ac410ae19d Mon Sep 17 00:00:00 2001 From: ArminJo Date: Tue, 27 May 2025 18:13:50 +0200 Subject: [PATCH 083/133] Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN --- .github/workflows/LibraryBuild.yml | 39 ++- README.md | 11 +- changelog.md | 2 + examples/AllProtocolsOnLCD/ADCUtils.hpp | 31 +- examples/SendDemo/SendDemo.ino | 4 +- examples/UnitTest/UnitTest.ino | 1 + src/IRSend.hpp | 44 ++- src/IRremote.hpp | 5 +- src/IRremoteInt.h | 2 +- src/ir_BangOlufsen.hpp | 4 +- src/private/IRTimer.hpp | 357 +++++++++++++++++++----- 11 files changed, 379 insertions(+), 121 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 93aee1426..d15cf90ac 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -51,6 +51,7 @@ jobs: - 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 @@ -83,18 +84,20 @@ jobs: include: - arduino-boards-fqbn: arduino:avr:uno build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=1200 -DIR_SEND_PIN=3 - 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 + IRremoteExtensionTest: -DIR_SEND_PIN=3 TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER 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 @@ -102,7 +105,8 @@ jobs: - arduino-boards-fqbn: arduino:avr:uno|SEND_PWM_BY_TIMER 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 @@ -110,22 +114,29 @@ 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: UnitTest # Sketch uses 28764 bytes (100%) of program storage space. Maximum is 28672 bytes @@ -133,37 +144,27 @@ jobs: - 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 - build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=750 - 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 # @@ -171,7 +172,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 @@ -179,6 +179,7 @@ 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 # @@ -188,15 +189,11 @@ jobs: 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 - build-properties: # the flags were put in compiler.cpp.extra_flags - IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=360 - 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 # # ATTinyCore diff --git a/README.md b/README.md index ab0b220b8..f84ee20f8 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) * [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) @@ -568,6 +569,11 @@ On **ESP32** ledc channel 0 is used for generating the IR PWM.
If `IR_SEND_PIN` is specified (as C macro), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro e.g. with `#undef IR_SEND_PIN`. Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library). +## Polarity of send pin +By default the polarity is HIGH for active and LOW for inactive or pause. +This corresponds to the connection schema: Pin -> Resistor-> IR-LED -> Ground.
+If you want to use the connection schema: VCC -> IR-LED -> Resistor -> Pin, you must specify `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN`. + ### List of public IR code databases http://www.harctoolbox.org/IR-resources.html @@ -864,9 +870,10 @@ Modify them by enabling / disabling them, or change the values if applicable. | `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | | `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the **advantage of more exact PWM generation**, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the **disadvantage of using a hardware timer**, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM gereration for each pin without using a shared resource (timer). | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | -| `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | +| `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverts 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. | | `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. | diff --git a/changelog.md b/changelog.md index 0ab56fa17..efe12b698 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,8 @@ # Changelog The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.4.3 +- Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN to make the software aware of reverse external connection. # 4.4.2 - Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4). diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 57a30a54c..989a7e859 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -27,6 +27,7 @@ #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) #define STR_HELPER(x) #x @@ -66,6 +67,11 @@ union WordUnionForADCUtils { #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 @@ -639,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(); @@ -655,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")); # 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 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) { @@ -820,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/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 79fd85e20..c04d3ae52 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -37,10 +37,12 @@ #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 // Reverts the polarity at the 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_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // 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! #if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85 #define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 07af75697..fc51b0678 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -88,6 +88,7 @@ //#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 diff --git a/src/IRSend.hpp b/src/IRSend.hpp index a2fafff19..756af9d9c 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -1165,7 +1165,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. @@ -1194,12 +1194,16 @@ void IRsend::mark(uint16_t aMarkMicros) { 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 @@ -1216,11 +1220,15 @@ void IRsend::mark(uint16_t aMarkMicros) { delayMicroseconds (periodOnTimeMicros); // On time is 8 us for 30% duty cycle. This is normally implemented by a blocking wait. /* - * Output the PWM pause + * Output the PWM pause - IR LED is inactive */ -# 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. +# 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 @@ -1321,20 +1329,28 @@ 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 diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 0a416a938..942e9aba6 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -46,9 +46,11 @@ * * - 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. @@ -247,6 +249,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 */ diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 17ea1f663..76e2953c4 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -262,7 +262,7 @@ class IRrecv { * Next 4 functions are also available as non member functions */ bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) - __attribute__ ((deprecated ("Remove second parameter, it is not supported any more! Third one was true by default."))); + __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); diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 628a5792e..f399741f6 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -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 diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 2e90423d2..be3c50c41 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -63,6 +63,13 @@ void disableSendPWMByTimer(); // Switch off PWM generation #undef IR_SEND_PIN // To avoid "warning: "IR_SEND_PIN" redefined". The user warning is done at IRremote.hpp line 202. #endif +#if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +// Use the inverse value, so same code should work for active Low output +#define IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH (100 - IR_SEND_DUTY_CYCLE_PERCENT) +#else +#define IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH IR_SEND_DUTY_CYCLE_PERCENT +#endif + // Macros for enabling timers for development //#define SEND_PWM_BY_TIMER //#define IR_USE_AVR_TIMER1 @@ -119,7 +126,7 @@ void timerDisableReceiveInterrupt() { /** * IF PWM should be generated not by software, but by a timer, this function sets output pin mode, - * configures the timer for generating a PWM with duty cycle of IR_SEND_DUTY_CYCLE_PERCENT + * configures the timer for generating a PWM with HIGH output level of duty cycle of IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * and disables the receive interrupt if it uses the same resource. * For most architectures, the pin number(s) which can be used for output is determined by the timer used! * The output of the PWM signal is controlled by enableSendPWMByTimer() and disableSendPWMByTimer(). @@ -339,6 +346,7 @@ void timerConfigForReceive() { } # if defined(SEND_PWM_BY_TIMER) +// Set IR_SEND_PIN depending on CPU # if defined(CORE_OC1A_PIN) #define IR_SEND_PIN CORE_OC1A_PIN // Teensy @@ -379,9 +387,9 @@ void timerConfigForReceive() { //#define IR_SEND_PIN PIN_PB6 // OC1AX / PB6 / Pin14 at ATTinyCore # endif -# else +# else // defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) #define IR_SEND_PIN 9 // OC1A Arduino Duemilanove, Diecimila, LilyPad, Sparkfun Pro Micro, Leonardo, MH-ET Tiny88 etc. -# endif // defined(CORE_OC1A_PIN) +# endif // Set IR_SEND_PIN depending on CPU # if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when down counting. @@ -395,20 +403,31 @@ void enableSendPWMByTimer() { //TCNT1 = 0; TCCR1A |= _BV(COM1B1); TCCR1D |= _BV(OC1BX); // + enable OC1BX as output } # else -void disableSendPWMByTimer() { +void enableSendPWMByTimer() { TCNT1 = 0; TCCR1A |= _BV(COM1A1); - TCCR1D |= _BV(OC1AU); // + enable OC1BU as output + TCCR1D |= _BV(OC1AU); // + enable OC1AU as output //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AV); // + enable OC1BV as output //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AW); // + enable OC1BW as output //TCNT1 = 0; TCCR1A |= _BV(COM1A1); TCCR1D |= _BV(OC1AX); // + enable OC1BX as output } +# endif // defined(USE_TIMER_CHANNEL_B) -# endif void disableSendPWMByTimer() { TCCR1D = 0; +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } -# else +# else // defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(USE_TIMER_CHANNEL_B) void enableSendPWMByTimer() { TCNT1 = 0; @@ -416,17 +435,40 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR1A &= ~(_BV(COM1B1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } -# else +# else // defined(USE_TIMER_CHANNEL_B) void enableSendPWMByTimer() { TCNT1 = 0; TCCR1A |= _BV(COM1A1); // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting. } void disableSendPWMByTimer() { TCCR1A &= ~(_BV(COM1A1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } -# endif -# endif +# endif // defined(USE_TIMER_CHANNEL_B) + +# endif // defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) /* * timerConfigForSend() is used exclusively by IRsend::enableIROut() @@ -435,31 +477,31 @@ void disableSendPWMByTimer() { void timerConfigForSend(uint16_t aFrequencyKHz) { timerDisableReceiveInterrupt(); -# if (((F_CPU / 2000) / 38) < 256) +# if (((F_CPU / 2000) / 38) < 256) const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM TCCR1A = _BV(WGM11); // PWM, Phase Correct, Top is ICR1 TCCR1B = _BV(WGM13) | _BV(CS10); // CS10 -> no prescaling ICR1 = tPWMWrapValue - 1; -# if defined(USE_TIMER_CHANNEL_B) - OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; -# else - OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; -# endif +# if defined(USE_TIMER_CHANNEL_B) + OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; +# else + OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; +# endif TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible -# else +# else const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM TCCR1A = _BV(WGM11);// PWM, Phase Correct, Top is ICR1 TCCR1B = _BV(WGM13) | _BV(CS11);// CS11 -> Prescaling by 8 ICR1 = tPWMWrapValue - 1; -# if defined(USE_TIMER_CHANNEL_B) - OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; -# else - OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; -# endif +# if defined(USE_TIMER_CHANNEL_B) + OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; +# else + OCR1A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; +# endif TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible -# endif +# endif // if (((F_CPU / 2000) / 38) < 256) } -# endif // defined(SEND_PWM_BY_TIMER) +# endif // defined(SEND_PWM_BY_TIMER) - Timer1 /* * AVR Timer2 (8 bits) // Tone timer on Uno @@ -473,7 +515,6 @@ void timerDisableReceiveInterrupt() { TIMSK2 = 0; } #define TIMER_INTR_NAME TIMER2_COMPB_vect // We use TIMER2_COMPB_vect to be compatible with tone() library - #define TIMER_COUNT_TOP (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND) void timerConfigForReceive() { @@ -493,6 +534,7 @@ void timerConfigForReceive() { } # if defined(SEND_PWM_BY_TIMER) +// Set IR_SEND_PIN depending on CPU # if defined(CORE_OC2B_PIN) #define IR_SEND_PIN CORE_OC2B_PIN // Teensy @@ -513,7 +555,7 @@ void timerConfigForReceive() { * Thus the OCR2A register cannot be used for comparing for channel A and TOP with OCR2B is not supported by Hardware :-(. */ #define IR_SEND_PIN 3 // Arduino Uno Pin PD3, Duemilanove, Diecimila, LilyPad, etc -# endif // defined(CORE_OC2B_PIN) +# endif // Set IR_SEND_PIN depending on CPU void enableSendPWMByTimer() { TCNT2 = 0; @@ -521,6 +563,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR2A &= ~(_BV(COM2B1)); // Normal port operation, OC2B disconnected. +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -540,14 +593,14 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { TCCR2A = _BV(WGM20); // PWM, Phase Correct, Top is OCR2A TCCR2B = _BV(WGM22) | _BV(CS20); // CS20 -> no prescaling OCR2A = tPWMWrapValue - 1; // The top value for the timer. The modulation frequency will be F_CPU / 2 / (OCR2A + 1). - OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT2 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible # else const uint16_t tPWMWrapValue = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM TCCR2A = _BV(WGM20);// PWM, Phase Correct, Top is OCR2A TCCR2B = _BV(WGM22) | _BV(CS21);// CS21 -> Prescaling by 8 OCR2A = tPWMWrapValue - 1; - OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR2B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT2 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible # endif } @@ -575,6 +628,7 @@ void timerConfigForReceive() { } # if defined(SEND_PWM_BY_TIMER) +// Set IR_SEND_PIN depending on CPU # if defined(CORE_OC3A_PIN) #define IR_SEND_PIN CORE_OC3A_PIN // Teensy @@ -587,7 +641,7 @@ void timerConfigForReceive() { # else #error Please add OC3A pin number here -# endif +# endif // Set IR_SEND_PIN depending on CPU void enableSendPWMByTimer() { TCNT3 = 0; @@ -595,6 +649,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR3A &= ~(_BV(COM3A1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -602,16 +667,16 @@ void disableSendPWMByTimer() { * Set output pin mode and disable receive interrupt if it uses the same resource */ void timerConfigForSend(uint16_t aFrequencyKHz) { -#if F_CPU > 16000000 +# if F_CPU > 16000000 #error "Creating timer PWM with timer 3 is not supported for F_CPU > 16 MHz" -#endif +# endif timerDisableReceiveInterrupt(); const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM TCCR3A = _BV(WGM31); TCCR3B = _BV(WGM33) | _BV(CS30); // PWM, Phase Correct, ICRn as TOP, complete period is double of tPWMWrapValue ICR3 = tPWMWrapValue - 1; - OCR3A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR3A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT3 = 0; // required, since we have an 16 bit counter } # endif // defined(SEND_PWM_BY_TIMER) @@ -636,6 +701,7 @@ void timerConfigForReceive() { } # if defined(SEND_PWM_BY_TIMER) +// Set IR_SEND_PIN depending on CPU # if defined(CORE_OC4A_PIN) #define IR_SEND_PIN CORE_OC4A_PIN # elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) @@ -650,18 +716,29 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR4A &= ~(_BV(COM4A1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } void timerConfigForSend(uint16_t aFrequencyKHz) { -#if F_CPU > 16000000 +# if F_CPU > 16000000 #error "Creating timer PWM with timer 4 is not supported for F_CPU > 16 MHz" -#endif +# endif timerDisableReceiveInterrupt(); const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM TCCR4A = _BV(WGM41); TCCR4B = _BV(WGM43) | _BV(CS40); ICR4 = tPWMWrapValue - 1; - OCR4A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR4A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT4 = 0; // required, since we have an 16 bit counter } # endif // defined(SEND_PWM_BY_TIMER) @@ -709,6 +786,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR4A &= ~(_BV(COM4A0)); // (Pro Micro does not map PC7 (32/ICP3/CLK0/OC4A) +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } // of ATmega32U4 ) # else @@ -719,6 +807,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR4A &= ~(_BV(COM4A1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } # endif @@ -740,8 +839,8 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { TCCR4E = 0; TC4H = tPWMWrapValue >> 8; OCR4C = tPWMWrapValue; - TC4H = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) >> 8; - OCR4A = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) & 255; + TC4H = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH / 100) >> 8; + OCR4A = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH / 100) & 255; TCNT4 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible } # endif // defined(SEND_PWM_BY_TIMER) @@ -781,6 +880,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR5A &= ~(_BV(COM5A1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -797,7 +907,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { TCCR5A = _BV(WGM51); TCCR5B = _BV(WGM53) | _BV(CS50); ICR5 = tPWMWrapValue - 1; - OCR5A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR5A = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT5 = 0; // required, since we have an 16 bit counter } # endif // defined(SEND_PWM_BY_TIMER) @@ -840,6 +950,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCCR0A &= ~(_BV(COM0B1)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -847,16 +968,16 @@ void disableSendPWMByTimer() { * Set output pin mode and disable receive interrupt if it uses the same resource */ void timerConfigForSend(uint16_t aFrequencyKHz) { -#if F_CPU > 16000000 +# if F_CPU > 16000000 #error "Creating timer PWM with timer TINY0 is not supported for F_CPU > 16 MHz" -#endif +# endif timerDisableReceiveInterrupt(); const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM TCCR0A = _BV(WGM00); // PWM, Phase Correct, Top is OCR0A TCCR0B = _BV(WGM02) | _BV(CS00); // CS00 -> no prescaling OCR0A = tPWMWrapValue - 1; - OCR0B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR0B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT0 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible } # endif // defined(SEND_PWM_BY_TIMER) @@ -899,6 +1020,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { GTCCR &= ~(_BV(PWM1B) | _BV(COM1B0)); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -912,14 +1044,14 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { const uint16_t tPWMWrapValue = (F_CPU / 1000) / (aFrequencyKHz); // 421 @16 MHz, 26 @1 MHz and 38 kHz TCCR1 = _BV(CTC1) | _BV(CS10);// CTC1 = 1: TOP value set to OCR1C, CS10 No Prescaling OCR1C = tPWMWrapValue - 1; - OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible GTCCR = _BV(PWM1B) | _BV(COM1B0);// PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match # else const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz); // 210 for 16 MHz and 38 kHz TCCR1 = _BV(CTC1) | _BV(CS11); // CTC1 = 1: TOP value set to OCR1C, CS11 Prescaling by 2 OCR1C = tPWMWrapValue - 1; - OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; + OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; TCNT1 = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible GTCCR = _BV(PWM1B) | _BV(COM1B0); // PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match # endif @@ -995,6 +1127,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCB0.CTRLB &= ~(TCB_CCMPEN_bm); +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -1011,7 +1154,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { const uint16_t tPWMWrapValue = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of using CLK / 2 TCB0.CTRLB = TCB_CNTMODE_PWM8_gc; // 8 bit PWM mode TCB0.CCMPL = tPWMWrapValue - 1; // Period of 8 bit PWM - TCB0.CCMPH = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; // Duty cycle of waveform of 8 bit PWM + TCB0.CCMPH = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; // Duty cycle of waveform of 8 bit PWM TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm); // use CLK / 2 TCB0.CNT = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible } @@ -1064,6 +1207,17 @@ void enableSendPWMByTimer() { } void disableSendPWMByTimer() { TCD0.CTRLA = 0; // do not disable output, disable complete timer +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) +# if defined(IR_SEND_PIN) + digitalWriteFast(IR_SEND_PIN, HIGH); +# else + if (__builtin_constant_p(sendPin)) { + digitalWriteFast(sendPin, HIGH); + } else { + digitalWrite(sendPin, HIGH); + } +# endif // defined(IR_SEND_PIN) +# endif // defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) } /* @@ -1084,7 +1238,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { // Generate duty cycle signal for debugging etc. TCD0.CMPASET = 0; - TCD0.CMPACLR = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT / 100) - 1; // duty cycle for WOA + TCD0.CMPACLR = (tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH / 100) - 1; // duty cycle for WOA TCD0.INTFLAGS = TCD_OVF_bm; // reset interrupt flags TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt @@ -1444,27 +1598,29 @@ void timerConfigForReceive() { # 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 // Variables specific to the ESP32. // the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code. hw_timer_t *s50usTimer = nullptr; // set by timerConfigForReceive() +#define _IRREMOTE_ESP32_LEDC_RESOLUTION 8 +#define _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE 255 -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) +//# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) +# if ESP_ARDUINO_VERSION < (3 << 16 + 0 >> 8 + 0) && !defined(SEND_LEDC_CHANNEL) #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif void timerEnableReceiveInterrupt() { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 + 0 >> 8 + 0) timerStart(s50usTimer); # else timerAlarmEnable(s50usTimer); # endif } -# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) +//# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) +# if ESP_ARDUINO_VERSION < (2 << 16 + 0 >> 8 + 2) /* * Special support for ESP core < 202 */ @@ -1478,7 +1634,8 @@ void timerDisableReceiveInterrupt() { void timerDisableReceiveInterrupt() { if (s50usTimer != nullptr) { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 + 0 >> 8 + 0) timerStop(s50usTimer); # else timerAlarmDisable(s50usTimer); @@ -1497,9 +1654,9 @@ void timerConfigForReceive() { // ESP32 has a proper API to setup timers, no weird chip macros needed // simply call the readable API versions :) // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true - if(s50usTimer == nullptr) { + if (s50usTimer == nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) - s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. + s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. timerStop(s50usTimer); // Stop it here, to avoid "error E (3447) gptimer: gptimer_start(348): timer is not enabled yet" at timerEnableReceiveInterrupt() timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); timerAlarm(s50usTimer, MICROS_PER_TICK, true, 0); // 0 in the last parameter is repeat forever @@ -1513,28 +1670,35 @@ void timerConfigForReceive() { } # endif - uint8_t sLastSendPin = 0; // Avoid multiple attach() or if pin changes, detach before attach # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) - ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API + ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE) / 100); // 3.x API # else - ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // 3.x API + ledcWrite(IrSender.sendPin, (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE) / 100); // 3.x API # endif # else // ESP version < 3.0 - ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT * 256) / 100); // * 256 since we have 8 bit resolution + ledcWrite(SEND_LEDC_CHANNEL, (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE) / 100); // * 256 since we have 8 bit resolution # endif } void disableSendPWMByTimer() { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + ledcWrite(IR_SEND_PIN, _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE); // 3.x API +# else ledcWrite(IR_SEND_PIN, 0); // 3.x API +# endif # else +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + ledcWrite(IrSender.sendPin, _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE); // 3.x API +# else ledcWrite(IrSender.sendPin, 0); // 3.x API +# endif # endif # else // ESP version < 3.0 @@ -1550,19 +1714,19 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) # if defined(IR_SEND_PIN) if(sLastSendPin == 0){ - ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, 8); // 3.x API + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API sLastSendPin = IR_SEND_PIN; } # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, 8); // 3.x API + ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API sLastSendPin = IrSender.sendPin; # endif # else // ESP version < 3.0 - ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, 8); // 8 bit PWM resolution + ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 8 bit PWM resolution # if defined(IR_SEND_PIN) ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel # else @@ -1736,6 +1900,7 @@ mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(IR_SEND_PIN)); mbed::PwmOut sPwmOutForSendPWM(digitalPinToPinName(IrSender.sendPin)); # endif uint8_t sIROutPuseWidth; +uint8_t sIROutPuseWidthForHigh; // for setting level to 1 void enableSendPWMByTimer() { sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidth); @@ -1744,7 +1909,11 @@ void enableSendPWMByTimer() { //void disableSendPWMByTimer() { sPwmOutForSendPWM.suspend();} // this kills pulsewidth_us value and does not set output level to LOW void disableSendPWMByTimer() { +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + sPwmOutForSendPWM.pulsewidth_us(sIROutPuseWidthForHigh); // this also sets output level to HIGH :-) +# else sPwmOutForSendPWM.pulsewidth_us(0); // this also sets output level to LOW :-) +# endif } /* @@ -1752,8 +1921,9 @@ void disableSendPWMByTimer() { * Set output pin mode and disable receive interrupt if it uses the same resource */ void timerConfigForSend(uint16_t aFrequencyKHz) { - sPwmOutForSendPWM.period_us(1000 / aFrequencyKHz); // 26.315 for 38 kHz - sIROutPuseWidth = (1000 * IR_SEND_DUTY_CYCLE_PERCENT) / (aFrequencyKHz * 100); + sIROutPuseWidthForHigh = 1000 / aFrequencyKHz; + sPwmOutForSendPWM.period_us(sIROutPuseWidthForHigh); // 26.315 for 38 kHz + sIROutPuseWidth = (1000 * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / (aFrequencyKHz * 100); } # endif // defined(SEND_PWM_BY_TIMER) @@ -1789,23 +1959,60 @@ void timerDisableReceiveInterrupt() { void timerConfigForReceive() { // no need for initializing timer at setup() } +#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. # if defined(SEND_PWM_BY_TIMER) #include "hardware/pwm.h" +#define USE_RP2040_NATIVE_COMMANDS +# if defined(USE_RP2040_NATIVE_COMMANDS) uint sSliceNumberForSendPWM; uint sChannelNumberForSendPWM; uint sIROutPuseWidth; +uint16_t sIROutPuseWidthForHigh; // for setting level to 1 +# else +uint sFrequency; +# endif /* * If we just disable the PWM, the counter stops and the output stays at the state is currently has */ void enableSendPWMByTimer() { +# if defined(USE_RP2040_NATIVE_COMMANDS) pwm_set_counter(sSliceNumberForSendPWM, 0); pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidth); +# else + analogWriteFreq(sFrequency); +# if defined(IR_SEND_PIN) + analogWrite(IR_SEND_PIN, (uint8_t) (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * 255 / 100)); // Calculate duty as 0-255 value (analogWrite uses 8-bit resolution) +# else + analogWrite(IrSender.sendPin, (uint8_t) (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * 255 / 100)); // Calculate duty as 0-255 value (analogWrite uses 8-bit resolution) +# endif +# endif } + void disableSendPWMByTimer() { +# if defined(USE_RP2040_NATIVE_COMMANDS) +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, sIROutPuseWidthForHigh); // this sets output also to HIGH +# else pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0); // this sets output also to LOW +# endif +# else +# if defined(IR_SEND_PIN) +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + analogWrite(IR_SEND_PIN, 255); // analogWrite(0) disables PWM and sets pin HIGH +# else + analogWrite(IR_SEND_PIN, 0); // analogWrite(0) disables PWM and sets pin LOW +# endif +# else +# if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) + analogWrite(IrSender.sendPin, 255); // analogWrite(0) disables PWM and sets pin HIGH +# else + analogWrite(IrSender.sendPin, 0); // analogWrite(0) disables PWM and sets pin LOW +# endif +# endif +# endif } /* @@ -1813,25 +2020,37 @@ void disableSendPWMByTimer() { * Set output pin mode and disable receive interrupt if it uses the same resource */ void timerConfigForSend(uint16_t aFrequencyKHz) { -# if defined(IR_SEND_PIN) +# if defined(USE_RP2040_NATIVE_COMMANDS) +# if defined(IR_SEND_PIN) gpio_set_function(IR_SEND_PIN, GPIO_FUNC_PWM); // Find out which PWM slice is connected to IR_SEND_PIN sSliceNumberForSendPWM = pwm_gpio_to_slice_num(IR_SEND_PIN); sChannelNumberForSendPWM = pwm_gpio_to_channel(IR_SEND_PIN); -# else +# else gpio_set_function(IrSender.sendPin, GPIO_FUNC_PWM); // Find out which PWM slice is connected to IR_SEND_PIN sSliceNumberForSendPWM = pwm_gpio_to_slice_num(IrSender.sendPin); sChannelNumberForSendPWM = pwm_gpio_to_channel(IrSender.sendPin); +# endif +# else +# if defined(IR_SEND_PIN) + pinMode(IR_SEND_PIN, OUTPUT); // Set the pin to output mode initially +# else + pinMode(IrSender.sendPin, OUTPUT); // Set the pin to output mode initially +# endif # endif +# if defined(USE_RP2040_NATIVE_COMMANDS) uint16_t tPWMWrapValue = (clock_get_hz(clk_sys)) / (aFrequencyKHz * 1000); // 3289.473 for 38 kHz @125 MHz clock. We have a 16 bit counter and use system clock (125 MHz) - pwm_config tPWMConfig = pwm_get_default_config(); + sIROutPuseWidthForHigh = tPWMWrapValue; pwm_config_set_wrap(&tPWMConfig, tPWMWrapValue - 1); pwm_init(sSliceNumberForSendPWM, &tPWMConfig, false); // we do not want to send now - sIROutPuseWidth = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT) / 100) - 1; // 985.84 for 38 kHz + sIROutPuseWidth = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; // 985.84 for 38 kHz pwm_set_chan_level(sSliceNumberForSendPWM, sChannelNumberForSendPWM, 0); pwm_set_enabled(sSliceNumberForSendPWM, true); +# else + sFrequency = aFrequencyKHz * 1000; +# endif } # endif // defined(SEND_PWM_BY_TIMER) @@ -1995,14 +2214,14 @@ void timerConfigForReceive() { # if defined(SEND_PWM_BY_TIMER) # if defined(IR_SEND_PIN) void enableSendPWMByTimer() { - analogWrite(IR_SEND_PIN, ((256L * 100) / IR_SEND_DUTY_CYCLE_PERCENT)), ir_out_kHz*1000); + analogWrite(IR_SEND_PIN, ((255L * 100) / IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH)), ir_out_kHz*1000); } void disableSendPWMByTimer() { analogWrite(IR_SEND_PIN, 0, ir_out_kHz*1000); } # else void enableSendPWMByTimer() { - analogWrite(IrSender.sendPin, ((256L * 100) / IR_SEND_DUTY_CYCLE_PERCENT), ir_out_kHz * 1000); + analogWrite(IrSender.sendPin, ((255L * 100) / IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH), ir_out_kHz * 1000); } void disableSendPWMByTimer() { analogWrite(IrSender.sendPin, 0, ir_out_kHz * 1000); From 5cff1b4e52f376ecb348e1a2aeaa8533051fa3d1 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 30 May 2025 01:15:03 +0200 Subject: [PATCH 084/133] Fixed spelling errors inspired by PR 1304 --- .github/ISSUE_TEMPLATE/bug_report.yml | 60 ++++-------- Contributing.md | 2 +- README.md | 97 ++++++++++++------- changelog.md | 10 +- examples/AllProtocolsOnLCD/LiquidCrystal.cpp | 26 ++++- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 +- .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/SendDemo/SendDemo.ino | 4 +- examples/UnitTest/UnitTest.ino | 3 + src/IRremoteInt.h | 4 +- src/ir_DistanceWidthProtocol.hpp | 8 +- src/ir_NEC.hpp | 2 +- 12 files changed, 128 insertions(+), 92 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 95c4245c1..eb97d831e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -11,40 +11,21 @@ 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 + id: Board_FQBN attributes: - label: The boards name or FQBN (e.g. esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80) for unspecified board. + label: Please specify **FQBN** (Fully Qualified Board Name). + It is the first line in the compiler output in the Arduino IDE 2.x. + 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. + label: The board manager URL used for exotic cores. value: "https://" 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,15 +89,15 @@ 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 @@ -128,12 +110,12 @@ 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 @@ -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 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/README.md b/README.md index f84ee20f8..10289a463 100644 --- a/README.md +++ b/README.md @@ -157,10 +157,11 @@ This library has been refactored, breaking backward compatibility with the old v ## 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`. +- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`. - Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar. - Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106) or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
@@ -172,7 +173,9 @@ If IR_SEND_PIN is not defined (before the line `#include `) you mu - Overflow, Repeat and other flags are now in [`IrReceiver.receivedIRData.flags`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRProtocol.h#L90-L101). - Seldom used: `results.rawbuf` and `results.rawlen` must be replaced by `IrReceiver.decodedIRData.rawDataPtr->rawbuf` and `IrReceiver.decodedIRData.rawDataPtr->rawlen`. -- The 5 protocols **NEC, Panasonic, Sony, Samsung and JVC** have been converted to LSB first. Send functions for sending old MSB data 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.
+- 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). ### Example @@ -241,29 +244,40 @@ 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. + +### 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`. +### IRremote functions +Use `bitreverseOneByte()` or `bitreverse32Bit()` for reversing. + +### Online tool which reverses every byte, but not the order of the bytes +Use this [tool provided by analysir](https://www.analysir.com/hex2nec.php). + +### Send MSB directly Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`.
## Errors when using the 4.x versions for old tutorials -If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
+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.
@@ -289,7 +303,8 @@ In the Arduino IDE the calls are executed when you click on *Verify* or *Upload* And now our problem with Arduino is:
**How to set [compile options](#compile-options--macros-for-this-library) for all *.cpp files, especially for libraries used?**
-IDE's like [Sloeber](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-sloeber-ide) or [PlatformIO](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project. +IDE's like [Sloeber](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-sloeber-ide) or +[PlatformIO](https://github.com/ArminJo/ServoEasing#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project. They add these options at each compiler call e.g. `-DTRACE`. But Arduino lacks this feature. @@ -425,7 +440,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++ @@ -545,32 +561,39 @@ 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()`. +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 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 as long as `IR_SEND_PIN` is **not** defined. This is because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
On **ESP32** ledc channel 0 is used for generating the IR PWM.
-If `IR_SEND_PIN` is specified (as C macro), it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must disable this `IR_SEND_PIN` macro e.g. with `#undef IR_SEND_PIN`. -Then you can change send pin at any time before sending an IR frame. See also [Compile options / macros for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-this-library). +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. +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`. @@ -687,12 +710,12 @@ See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/b ## 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();}`.
@@ -725,7 +748,8 @@ 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 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`. +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`. @@ -739,7 +763,8 @@ The examples are available at File > Examples > Examples from Custom Libraries / 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. +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. A simple example can be tested online with [WOKWI](https://wokwi.com/projects/338611596994544210). #### SimpleReceiverForHashCodes @@ -764,7 +789,8 @@ If the protocol is not NEC and code size matters, look at this [example](https:/ #### 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.
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](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).
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**. @@ -782,7 +808,8 @@ Demonstrates sending IR codes toggling between 2 **different send pins**. 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 appropriate protocol encoder. `UNKNOWN` protocol frames are stored as raw data and sent with `sendRaw()`. +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 Try to decode each IR frame with the *universal* **DistanceWidth decoder**, store the data and send it on button press with `sendPulseDistanceWidthFromArray()`.
@@ -868,9 +895,9 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverts 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_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_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. | @@ -889,10 +916,10 @@ These next macros for **TinyIRReceiver** must be defined in your program before |-|-:|-| | `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 codefor send and receive. Saves 14 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 addres and command parity checks. Saves 48 bytes program memory. | +| `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. | @@ -1055,7 +1082,7 @@ This works on AVR boards like Uno because each call to` tone()` completely initi 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/master/examples/SimpleSender/PinDefinitionsAndMore.h#L334), 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#L334),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): @@ -1070,7 +1097,9 @@ Due to automatic gain control and other bias effects, high intensity of the 38 k 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.
+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.
diff --git a/changelog.md b/changelog.md index efe12b698..bfed8d0e1 100644 --- a/changelog.md +++ b/changelog.md @@ -69,14 +69,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(). @@ -147,7 +147,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. @@ -382,7 +382,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 @@ -410,4 +410,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/LiquidCrystal.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp index 5dcef0838..8a6e7fa21 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. } /*********** 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/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 352200211..5a0935998 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -222,7 +222,7 @@ void storeCode() { /* * Print info */ - Serial.print(F("Received unknown code and store ")); + Serial.print(F("Received unknown or pulse width/distance code and store ")); Serial.print(IrReceiver.decodedIRData.rawDataPtr->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 diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index a932e91ac..31391cb57 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 diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index c04d3ae52..8aa9e0d64 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -39,11 +39,11 @@ #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 // Reverts the polarity at the send pin. +//#define USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin. +//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition //#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal. -//#define 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! #if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85 #define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory #endif diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index fc51b0678..a6ca7fcff 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -46,8 +46,11 @@ //#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_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN // Reverses the polarity at the send pin. +//#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition +//#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal. #if FLASHEND <= 0x7FFF // For 32k flash or less, like ATmega328 #define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory #endif diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 76e2953c4..1fe279796 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -666,7 +666,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); @@ -676,7 +676,7 @@ 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); #if !defined(IR_SEND_PIN) diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index dfbe12440..0012625c1 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -192,17 +192,21 @@ 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: ")); diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 5ebcc878a..6302b424b 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -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: +// ONKYO (sometimes called NECext): like NEC but force to 16 independent address and 16 bit command bits: // Standard NEC sends a special fixed repeat frame. // NEC2: like NEC, but for repeat, the same full frame is sent after the 110 ms. I have a DVD remote with NEC2. // NEC and NEC 2 only differ in the repeat frames, so the protocol can only be detected correctly after the first repeat. From 6d11b6a82745622e6192fcafba27aa8fcb196cf4 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 29 Jun 2025 10:47:30 +0200 Subject: [PATCH 085/133] Bumped version to 4.4.3 --- changelog.md | 7 ++++++- keywords.txt | 36 ++++++++++++++++++++++++++++++++++-- library.json | 4 ++-- library.properties | 2 +- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index bfed8d0e1..7a6d54119 100644 --- a/changelog.md +++ b/changelog.md @@ -1,8 +1,13 @@ # Changelog The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.4.4 + + # 4.4.3 -- Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN to make the software aware of reverse external connection. +- 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). diff --git a/keywords.txt b/keywords.txt index adfe84678..a67cd0ed8 100644 --- a/keywords.txt +++ b/keywords.txt @@ -128,13 +128,45 @@ MAGIQUEST LITERAL1 WHYNTER LITERAL1 FAST LITERAL1 -FEEDBACK_LED_IS_ACTIVE_LOW 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 +DECODE_STRICT_CHECKS 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 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_SEND_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 c0666baa1..62260bdf3 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.4.2", + "version": "4.4.3", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", @@ -27,7 +27,7 @@ ], "license": "MIT", "frameworks": "arduino", - "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], + "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 40e043e2a..b5c0b1eb2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.4.2 +version=4.4.3 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols From c006bfaac57defb55dc969cb8c1f327b0a159511 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 4 Jul 2025 09:11:36 +0200 Subject: [PATCH 086/133] Closes #1306 - bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. --- .github/workflows/LibraryBuild.yml | 19 +++++++++++++++---- Contributors.md | 1 + changelog.md | 1 + examples/ReceiveDemo/ReceiveDemo.ino | 8 ++++---- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index d15cf90ac..6ea8fc566 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -72,6 +72,7 @@ jobs: - 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 @@ -244,15 +245,25 @@ jobs: 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! - IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 - All: -DRAW_BUFFER_LENGTH=750 -MMD -c +# IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 +# All: -DRAW_BUFFER_LENGTH=750 -MMD -c + 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 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: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 - All: -DRAW_BUFFER_LENGTH=750 -MMD -c +# IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 +# All: -DRAW_BUFFER_LENGTH=750 -MMD -c + All: -DRAW_BUFFER_LENGTH=1000 + + - 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! +# IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 +# All: -DRAW_BUFFER_LENGTH=750 -MMD -c + All: -DRAW_BUFFER_LENGTH=750 # # STM diff --git a/Contributors.md b/Contributors.md index f016310a7..9df2e50aa 100644 --- a/Contributors.md +++ b/Contributors.md @@ -33,5 +33,6 @@ These are the active contributors of this project that you may contact if there - [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. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/changelog.md b/changelog.md index 7a6d54119..0ffd0ffcf 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.4.4 +- Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306. # 4.4.3 diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 44fa78e69..5c8b09f80 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -113,9 +113,9 @@ #if defined(APPLICATION_PIN) #define DEBUG_BUTTON_PIN APPLICATION_PIN // if low, print timing for each received data set #else -#define DEBUG_BUTTON_PIN 6 +#define DEBUG_BUTTON_PIN 6 #endif -#if defined(ESP32) +#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 @@ -230,9 +230,9 @@ void loop() { */ if (IrReceiver.decodedIRData.protocol == UNKNOWN #if defined(DEBUG_BUTTON_PIN) - || digitalRead(DEBUG_BUTTON_PIN) == LOW) + || 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")); From dd1e964b797fb253fea92e69c1a37f29d30883bd Mon Sep 17 00:00:00 2001 From: ArminJo Date: Tue, 15 Jul 2025 08:42:49 +0200 Subject: [PATCH 087/133] Clip tick count for rawbuf at 255, closes #1309 - dead link. --- .github/workflows/LibraryBuild.yml | 10 +- README.md | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 12 +- examples/SendDemo/SendDemo.ino | 25 +- examples/UnitTest/UnitTest.ino | 69 +- examples/UnitTest/UnitTest.log | 2063 ++++++++++++++++++-------- examples/UnitTest/UnitTest_64bit.log | 1481 ++++++++++-------- src/IRReceive.hpp | 41 +- src/ir_BangOlufsen.hpp | 83 +- src/ir_MagiQuest.hpp | 4 - 10 files changed, 2467 insertions(+), 1323 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 6ea8fc566..ec5dccc66 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -245,25 +245,19 @@ jobs: 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! -# IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 -# All: -DRAW_BUFFER_LENGTH=750 -MMD -c 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 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: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 -# All: -DRAW_BUFFER_LENGTH=750 -MMD -c - All: -DRAW_BUFFER_LENGTH=1000 + 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! -# IRremoteExtensionTest: -MMD -c # see https://github.com/espressif/arduino-esp32/issues/8815 -# All: -DRAW_BUFFER_LENGTH=750 -MMD -c - All: -DRAW_BUFFER_LENGTH=750 + All: -DRAW_BUFFER_LENGTH=1500 # # STM diff --git a/README.md b/README.md index 10289a463..f9860b22a 100644 --- a/README.md +++ b/README.md @@ -1025,7 +1025,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 diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 5c8b09f80..b4c3edd10 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -110,10 +110,10 @@ #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 +#define DEBUG_BUTTON_PIN 6 #endif #if defined(ESP32) && defined(DEBUG_BUTTON_PIN) # if !digitalPinIsValid(DEBUG_BUTTON_PIN) @@ -132,7 +132,7 @@ void setup() { # endif #endif - Serial.begin(9600); + Serial.begin(115200); #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) || (defined(ESP32) && defined(ARDUINO_USB_MODE)) @@ -169,11 +169,7 @@ void setup() { Serial.println(); # if defined(DEBUG_BUTTON_PIN) Serial.print(F("If you connect debug pin ")); -# if defined(APPLICATION_PIN_STRING) - Serial.print(APPLICATION_PIN_STRING); -# else Serial.print(DEBUG_BUTTON_PIN); -# endif Serial.println(F(" to ground, raw data is always printed and tone is disabled")); # endif diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 8aa9e0d64..bafc8852c 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -208,7 +208,7 @@ void loop() { IrSender.sendNECMSB(0x40802CD3, 32, false); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 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 IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant @@ -221,7 +221,7 @@ 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 PGM")); + 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 @@ -247,7 +247,7 @@ void loop() { # 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 tRawData[0] = 0x87654321; // LSB of tRawData[0] is sent first @@ -263,7 +263,7 @@ void loop() { # 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 @@ -274,20 +274,31 @@ void loop() { # 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); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index a6ca7fcff..947b9457e 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -106,11 +106,16 @@ //#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below #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 @@ -132,7 +137,9 @@ uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/ #endif void setup() { +#if defined(DEBUG_BUTTON_PIN) pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP); +#endif Serial.begin(115200); @@ -189,13 +196,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) @@ -237,7 +242,11 @@ 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) { + 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); } @@ -282,7 +291,11 @@ 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) { + 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); } @@ -347,7 +360,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); } @@ -420,10 +437,12 @@ void loop() { * Complete NEC frames as repeats to force decoding as NEC2 are tested here */ for (int8_t i = 0; i < sRepeats; i++) { +#if defined(DEBUG_BUTTON_PIN) if (digitalRead(DEBUG_BUTTON_PIN) != LOW) { // If debug is enabled, printing time (50 ms) is sufficient as delay delayMicroseconds(NEC_REPEAT_DISTANCE - 20000); // 20000 is just a guess } +#endif IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); } @@ -499,7 +518,7 @@ void loop() { delay(DELAY_AFTER_SEND); # if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) - Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 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 IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant @@ -513,12 +532,12 @@ 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 PGM")); + 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.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48, - PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); + 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, @@ -546,7 +565,7 @@ 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 @@ -560,7 +579,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 @@ -571,7 +590,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); @@ -579,7 +598,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 @@ -597,7 +616,7 @@ void loop() { # 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 @@ -610,7 +629,7 @@ 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]; @@ -623,21 +642,21 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send 7 bit ASCII character with 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 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); checkReceive(sAddress & 0x1F, sCommand & 0x7F); delay(DELAY_AFTER_SEND); - 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(); IrSender.sendPulseDistanceWidth(38, 1000, 500, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0x87654321); @@ -648,7 +667,7 @@ void loop() { # endif // if FLASHEND >= 0x7FFF ... # 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 IRRawDataType tRawData1[2]; @@ -658,7 +677,7 @@ void loop() { 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) { @@ -800,14 +819,15 @@ void loop() { # 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); + Serial.println(F("- Now try to decode the first 6 entries, which results in rawData 0x0")); uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen; + IrReceiver.decodedIRData.rawlen = 6; IrReceiver.decodedIRData.rawDataPtr->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 @@ -820,6 +840,7 @@ void loop() { for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { IrReceiver.decodedIRData.rawDataPtr->rawbuf[i] = IrReceiver.decodedIRData.rawDataPtr->rawbuf[i + 6]; } + IrReceiver.decodedIRData.initialGapTicks = IrReceiver.decodedIRData.rawDataPtr->rawbuf[0]; # endif checkReceive(sAddress & 0x0FF, sCommand); delay(DELAY_AFTER_SEND); diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 4063d890c..6e5a43fe3 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 +START ../src/UnitTest.cpp from Jul 15 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 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,683 +12,788 @@ 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 Duration=67850 us +Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Gap=1049200us Duration=67800us Send with: IrSender.sendNEC(0xF1, 0x76, ); -rawData[68]: +rawData[68]: -1049200 - +8950,-4350 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + +8950,-4400 + + 600,-1600 + 650,- 500 + 600,- 500 + 600,- 550 + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 550 + 600,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650 -Duration=67850 us +Duration=67800us + Send NEC with 16 bit address -Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Duration=73350 us +Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1061800us Duration=73350us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: - -1060600 +rawData[68]: + -1061800 +8950,-4400 - + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650 -Duration=73350 us +Duration=73350us + Send NEC2 with 16 bit address -Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Duration=73400 us +Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1062300us Duration=73400us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); -rawData[68]: - -1061100 +rawData[68]: + -1062300 +8950,-4400 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,- 550 + 600,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650 +Duration=73400us + + +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 Gap=1071050us Duration=67900us +Send with: IrSender.sendNEC(0x80, 0x45, ); +rawData[68]: + -1071050 + +9100,-4350 + + 650,- 500 + 650,- 500 + 650,- 600 + 550,- 550 + + 650,- 500 + 650,- 500 + 650,- 500 + 650,-1600 + + 650,-1550 + 650,-1550 + 650,-1600 + 600,-1550 + + 700,-1500 + 650,-1600 + 650,-1550 + 650,- 500 + + 650,-1550 + 650,- 500 + 650,-1600 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 450 + + 700,- 450 + 700,-1500 + 650,- 500 + 650,-1600 + + 650,-1550 + 650,-1550 + 650,- 500 + 650,-1550 + + 650 +Duration=67900us + + +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 Gap=1068200us Duration=68000us +Send with: IrSender.sendNEC(0x4, 0x8, ); +rawData[68]: + -1068200 + +8950,-4400 + + 650,- 500 + 650,- 450 + 650,-1600 + 650,- 500 + + 600,- 550 + 600,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 650,-1600 + 650,- 500 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 550 + 550,- 550 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + 650 -Duration=73400 us +Duration=68000us -Send Panasonic 0xB, 0x10 as 48 bit PulseDistance using ProtocolConstants -Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Duration=54150 us + +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=1066450us Duration=55550us +Send with: IrSender.sendOnkyo(0x102, 0x304, ); +rawData[68]: + -1066450 + +8950,-4350 + + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,- 500 + 650,- 550 + 600,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600 +Duration=55550us + + +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=1068300us Duration=61150us +Send with: IrSender.sendNEC(0x102, 0x34, ); +rawData[68]: + -1068300 + +8950,-4400 + + 650,- 450 + 650,-1600 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,- 500 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,-1600 + 650,-1600 + + 600 +Duration=61150us + + +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=1067800us Duration=54200us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1064750 +rawData[100]: + -1067800 +3500,-1650 - + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1250 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 350 - + 500,-1250 + 500,- 350 + 500,- 400 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 500,- 350 + 500,-1250 + 450,- 400 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 + + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 450 + + 450,- 400 + 500,- 350 + 450,- 450 + 450,- 400 + + 500,-1250 + 450,- 400 + 450,- 400 + 500,- 400 + + 450,- 400 + 500,- 350 + 450,- 450 + 450,- 400 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1250 + 450 -Duration=54150 us +Duration=54200us -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 Duration=53200 us +Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Gap=1084800us Duration=53200us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1081400 +rawData[100]: + -1084800 +3450,-1650 - + 550,- 300 + 500,-1200 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,-1150 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 550,- 300 + 500,- 350 + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400 + + 450,-1200 + 500,-1200 + 500,- 350 + 500,-1200 + 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 + 550,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 300 - + 550,-1150 + 500,- 400 + 450,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 550,- 300 + 500,-1200 + 500,- 350 + 500,-1200 - + 500 -Duration=53200 us + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400 + + 500,- 350 + 500,- 400 + 450,- 350 + 500,- 350 + + 500,-1200 + 500,- 400 + 450,- 350 + 500,- 350 + + 500,- 400 + 450,- 350 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1250 + + 450 +Duration=53200us + -MSB first -Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Duration=53200 us +Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Gap=1077450us Duration=53200us Send with: IrSender.sendPanasonic(0xB, 0x10, ); -rawData[100]: - -1076300 - +3450,-1650 - + 500,- 350 + 550,-1150 + 500,- 400 + 500,- 300 - + 550,- 300 + 550,- 300 + 500,- 350 + 550,- 300 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 +rawData[100]: + -1077450 + +3500,-1650 + + 500,- 350 + 500,-1200 + 500,- 300 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 + + 500,- 350 + 500,- 400 + 450,- 350 + 500,- 350 + + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 400 + + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,-1200 + 500,-1200 + 500,- 350 + 500,-1200 + + 500,- 350 + 500,- 350 + 550,- 300 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 550,- 300 + 500,- 400 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 300 - + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,-1200 + 500,- 300 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1200 + 500 -Duration=53200 us +Duration=53200us -Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first -Protocol=PulseDistance Raw-Data=0x5A 72 bits LSB first Duration=138400 us -Send on a 8 bit platform 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=1084300us Duration=138250us +Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A}; - IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4400, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); -rawData[148]: - -1081200 - +8900,-4400 - + 600,-1600 + 600,- 550 + 600,- 550 + 600,- 550 + IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); +rawData[148]: + -1084300 + +8850,-4400 + + 600,-1600 + 650,- 500 + 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,- 550 + 600,-1650 + 600,- 600 + + 550,- 550 + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 550 - + 600,- 550 + 600,- 550 + 600,- 550 + 600,-1650 - + 650,-1600 + 600,- 550 + 600,- 550 + 600,-1650 + + 600,- 550 + 600,- 550 + 600,- 550 + 600,-1700 + + 600,-1600 + 600,- 550 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1600 + 600,- 550 + 600,- 550 + 600,-1650 + 600,-1650 - + 550,-1700 + 600,- 550 + 600,-1650 + 600,-1650 - + 600,- 550 + 600,-1650 + 600,-1650 + 600,-1650 - + 550,-1650 + 600,-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,-1650 + + 600,- 550 + 600,-1600 + 600,-1650 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600 + + 600,- 550 + 650,-1600 + 600,- 550 + 600,-1650 + + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600 -Duration=138400 us +Duration=138250us -Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first -Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Duration=48250 us -Send on a 8 bit platform with: + +Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300 +Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Gap=1121150us Duration=48300us +Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[108]: - -1118250 - + 350,- 550 - + 400,- 500 + 700,- 200 + 650,- 250 + 700,- 200 - + 650,- 250 + 400,- 550 + 650,- 250 + 650,- 250 - + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 - + 650,- 250 + 650,- 200 + 400,- 550 + 650,- 200 + IrSender.sendPulseDistanceWidthFromArray(38, 400, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); +rawData[108]: + -1121150 + + 400,- 550 + + 350,- 550 + 650,- 250 + 650,- 250 + 600,- 300 + + 650,- 250 + 350,- 550 + 650,- 250 + 650,- 250 + + 350,- 550 + 400,- 500 + 650,- 250 + 650,- 250 + + 650,- 250 + 700,- 200 + 400,- 500 + 650,- 250 + 400,- 550 + 650,- 200 + 400,- 550 + 650,- 200 - + 700,- 200 + 400,- 550 + 350,- 550 + 650,- 250 + + 700,- 250 + 350,- 550 + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 550 - + 400,- 550 + 650,- 250 + 650,- 200 + 400,- 500 - + 700,- 200 + 400,- 550 + 650,- 250 + 350,- 550 + + 400,- 550 + 650,- 250 + 650,- 250 + 350,- 550 + + 650,- 250 + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 + 350,- 550 + 650,- 250 + 400,- 500 - + 700,- 250 + 650,- 250 + 350,- 550 + 350,- 550 - + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 - + 400 -Duration=48250 us + + 700,- 200 + 650,- 250 + 400,- 550 + 350,- 550 + + 400,- 500 + 650,- 250 + 400,- 500 + 400,- 550 + + 350 +Duration=48300us -Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data -Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Duration=48500 us -Send on a 8 bit platform with: + +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=1100850us Duration=48500us +Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[108]: - -1097950 - + 350,- 550 - + 400,- 500 + 650,- 250 + 650,- 250 + 650,- 250 - + 650,- 250 + 400,- 500 + 700,- 200 + 700,- 250 - + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 - + 650,- 250 + 650,- 250 + 350,- 550 + 650,- 250 - + 350,- 550 + 650,- 250 + 350,- 550 + 650,- 250 - + 650,- 250 + 400,- 550 + 350,- 500 + 650,- 250 - + 400,- 500 + 400,- 500 + 400,- 550 + 650,- 250 - + 650,- 200 + 700,- 200 + 650,- 250 + 400,- 550 - + 400,- 500 + 650,- 250 + 650,- 250 + 400,- 550 - + 600,- 250 + 400,- 500 + 650,- 250 + 400,- 550 + IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); +rawData[108]: + -1100850 + + 350,- 600 + + 350,- 550 + 650,- 250 + 650,- 250 + 650,- 250 + + 650,- 200 + 400,- 550 + 650,- 200 + 650,- 250 + + 400,- 500 + 400,- 550 + 650,- 250 + 650,- 200 + + 650,- 250 + 700,- 200 + 400,- 500 + 700,- 200 + + 400,- 550 + 650,- 250 + 350,- 550 + 650,- 250 + + 650,- 250 + 350,- 550 + 400,- 500 + 650,- 250 + + 400,- 500 + 400,- 550 + 350,- 550 + 650,- 250 + + 650,- 250 + 650,- 200 + 650,- 300 + 350,- 550 + + 350,- 550 + 650,- 250 + 650,- 250 + 400,- 500 + + 700,- 250 + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 + 350,- 550 + 650,- 250 + 350,- 550 + 650,- 250 + 650,- 250 + 350,- 550 + 350,- 550 - + 350,- 550 + 650,- 250 + 350,- 550 + 400,- 500 + + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 + 650 -Duration=48500 us +Duration=48500us -Send 7 bit ASCII character with PulseDistanceWidth LSB first -Protocol=PulseDistance Raw-Data=0x76 7 bits LSB first Duration=20950 us + +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=1098850us 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]: - -1095750 +rawData[18]: + -1098850 +6000,- 450 - +1550,- 450 + 550,-1400 + 550,-1450 +1550,- 450 + +1550,- 400 + 550,-1450 + 550,-1450 +1550,- 450 + 550,-1450 + 550,-1450 + 550,-1450 + 550 -Duration=20950 us +Duration=20950us + -Send Sony12 as PulseWidth LSB first -Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Duration=21050 us +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=1041700us Duration=21000us Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: - -1038650 - +2500,- 500 - + 700,- 500 +1250,- 550 +1250,- 550 + 650,- 550 +rawData[26]: + -1041700 + +2450,- 550 + + 650,- 550 +1250,- 500 +1250,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 +1250 -Duration=21050 us +Duration=21000us -Send 32 bit PulseWidth 0x87654321 LSB first -Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first Duration=24650 us + +Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 +Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first Gap=1041200us Duration=24600us Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1100, 450, 650, 250, 350, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); -rawData[66]: - -1038250 +rawData[66]: + -1041200 +1100,- 450 - + 600,- 300 + 350,- 250 + 350,- 250 + 400,- 200 - + 400,- 250 + 600,- 300 + 350,- 250 + 350,- 250 - + 650,- 250 + 650,- 250 + 400,- 250 + 350,- 250 - + 350,- 250 + 400,- 200 + 650,- 250 + 400,- 250 - + 650,- 250 + 350,- 250 + 650,- 250 + 350,- 250 - + 350,- 250 + 650,- 250 + 700,- 200 + 400,- 250 - + 650,- 200 + 700,- 200 + 700,- 200 + 400,- 250 - + 350,- 250 + 350,- 250 + 400,- 200 + 700 -Duration=24650 us - -Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first Duration=63850 us -Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first + + 650,- 250 + 400,- 200 + 400,- 200 + 400,- 250 + + 350,- 250 + 650,- 250 + 350,- 250 + 400,- 200 + + 700,- 200 + 700,- 250 + 350,- 250 + 350,- 250 + + 350,- 250 + 400,- 200 + 700,- 200 + 400,- 250 + + 650,- 250 + 350,- 250 + 650,- 250 + 400,- 200 + + 400,- 250 + 650,- 250 + 650,- 250 + 350,- 250 + + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 250 + + 350,- 250 + 350,- 250 + 350,- 250 + 650 +Duration=24600us + + +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=1070650us Duration=63950us Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); rawData[112]: - -1065600 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + -1070650 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 - + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550 + + 350,- 800 + 350,- 800 + 350,- 850 + 300,- 800 + + 650,- 550 + 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 - + 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 - + 600,- 550 + 350,- 800 + 350,- 800 + 600 -Duration=63850 us + + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 + + 350,- 850 + 350,- 800 + 300,- 800 + 350,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 550 + 600,- 550 + + 300,- 800 + 650,- 550 + 600,- 550 + 300,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 500 + + 650,- 500 + 350,- 800 + 350,- 800 + 650 +Duration=63950us + Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Duration=76750 us +Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Gap=1087450us Duration=76750us Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); -rawData[68]: - -1115300 +rawData[68]: + -1087450 +8950,-4400 + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600 -Duration=76750 us + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + + 650 +Duration=76750us + Send Apple -Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Duration=72250 us +Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Gap=1061400us Duration=72250us Send with: IrSender.sendApple(0xF1, 0x76, ); -rawData[68]: - -1060250 +rawData[68]: + -1061400 +8950,-4400 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600 -Duration=72250 us + + 650,- 500 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1650 + + 600,-1600 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 450 + + 650,-1600 + 650,- 450 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650 +Duration=72250us + Send Panasonic -Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Duration=64450 us +Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Gap=1061100us Duration=64450us Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); -rawData[100]: - -1059900 - +3500,-1650 - + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 +rawData[100]: + -1061100 + +3450,-1700 + + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 400 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,-1250 + 500,-1200 - + 500,-1200 + 500,-1250 + 500,-1200 + 500,-1250 - + 500,- 400 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,-1250 - + 450,-1250 + 500,- 350 + 500,- 400 + 450,-1250 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 450,-1250 + 500,- 400 + 500,- 350 + 500,- 400 + + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1200 + + 500,-1250 + 500,-1200 + 500,-1250 + 450,-1300 + + 450,- 400 + 450,-1250 + 450,-1300 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,-1250 + 500,- 400 + + 450,-1250 + 500,- 350 + 500,- 400 + 500,-1200 + + 500,-1250 + 500,- 350 + 500,- 400 + 450,-1250 + 500 -Duration=64450 us +Duration=64450us + Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first Duration=69550 us +Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first Gap=1081300us Duration=69550us Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); -rawData[100]: - -1080100 - +3450,-1700 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 +rawData[100]: + -1081300 + +3500,-1650 + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,- 400 + 450,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1300 - + 450,- 400 + 500,-1200 + 500,-1250 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1250 - + 450,-1250 + 500,- 400 + 450,- 400 + 500,-1200 - + 500 -Duration=69550 us + + 500,-1250 + 500,-1200 + 500,-1250 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,-1250 + 500,- 350 + + 500,-1250 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,-1250 + 450,- 400 + 500,- 350 + 450,- 450 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 500,- 350 + 500,-1250 + 450,-1250 + 500,- 350 + + 500,-1250 + 500,-1200 + 500,-1250 + 500,- 350 + + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 + + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 + + 450 +Duration=69550us + Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Duration=67900 us +Protocol=Kaseikyo_Denon Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Gap=1082100us Duration=67850us Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, ); -rawData[100]: - -1080850 - +3500,-1650 - + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,-1250 + 450,- 400 + 500,-1200 + 500,- 400 - + 500,- 350 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 500,-1200 + 500,-1250 + 500,-1250 - + 450,-1250 + 500,-1250 + 500,-1200 + 500,-1250 - + 500,- 350 + 500,-1250 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,-1250 + 500,-1200 + 500,- 350 - + 500,-1250 + 500,- 350 + 500,- 350 + 500,-1250 - + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 - + 500 -Duration=67900 us +rawData[100]: + -1082100 + +3450,-1700 + + 500,- 350 + 500,- 350 + 500,-1250 + 500,- 350 + + 500,-1250 + 500,- 350 + 500,-1250 + 450,- 400 + + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 + + 500,- 400 + 500,-1200 + 500,-1250 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,- 400 + 450,- 400 + 500,-1250 + + 450,-1250 + 500,- 400 + 500,- 350 + 500,-1250 + + 450 +Duration=67850us + Send Denon -Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Duration=23150 us +Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Gap=1079850us Duration=23150us Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: - -1078600 +rawData[32]: + -1079850 + 300,-1750 + 300,- 750 + 300,- 750 + 300,- 750 + 300,-1750 + 350,- 700 + 350,-1700 + 350,-1750 - + 300,- 750 + 300,-1750 + 350,-1700 + 350,-1750 - + 300,- 750 + 300,- 750 + 300,- 700 + 350 -Duration=23150 us + + 300,- 750 + 300,-1750 + 350,-1750 + 250,-1800 + + 350,- 700 + 350,- 700 + 300,- 750 + 300 +Duration=23150us + Send Denon/Sharp variant -Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x2ED1 15 bits LSB first Duration=24200 us +Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x2ED1 15 bits LSB first Gap=1022000us Duration=24200us Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: - -1020800 +rawData[32]: + -1022000 + 300,-1750 + 350,- 700 + 350,- 700 + 300,- 750 - + 300,-1750 + 350,- 700 + 350,-1700 + 350,-1750 - + 350,- 700 + 300,-1750 + 350,-1750 + 300,-1750 - + 350,- 700 + 350,-1700 + 350,- 700 + 350 -Duration=24200 us - -Send Sony/SIRCS with 7 command and 5 address bits -Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Duration=21050 us -Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: - -1023000 - +2450,- 550 - + 700,- 500 +1300,- 500 +1250,- 550 + 650,- 550 - +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 - + 700,- 500 + 600,- 600 + 650,- 550 +1250 -Duration=21050 us + + 300,-1750 + 350,- 700 + 350,-1700 + 300,-1800 + + 300,- 750 + 300,-1750 + 350,-1750 + 300,-1750 + + 350,- 700 + 350,-1750 + 300,- 700 + 350 +Duration=24200us -Send Sony/SIRCS with 7 command and 8 address bits -Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Duration=26450 us -Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); -rawData[32]: - -1038750 - +2450,- 550 - + 700,- 500 +1250,- 550 +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 -Duration=26450 us Send Sony/SIRCS with 7 command and 5 address bits -Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Duration=21050 us +Protocol=Sony Address=0x11 Command=0x76 Raw-Data=0x8F6 12 bits LSB first Gap=1024200us Duration=21050us Send with: IrSender.sendSony(0x11, 0x76, 2, 12); rawData[26]: - -1020900 - +2450,- 550 + -1024200 + +2500,- 500 + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 +1250 -Duration=21050 us +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 Duration=26450 us +Protocol=Sony Address=0xF1 Command=0x76 Raw-Data=0x78F6 15 bits LSB first Gap=1040000us Duration=26400us Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); rawData[32]: - -1036650 - +2450,- 550 + -1040000 + +2400,- 550 + 650,- 550 +1250,- 550 +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 -Duration=26450 us +Duration=26400us + Send Sony/SIRCS with 7 command and 13 address bits -Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Duration=35400 us +Protocol=Sony Address=0x1FF1 Command=0x76 Raw-Data=0xFF8F6 20 bits LSB first Gap=1043700us Duration=35450us Send with: IrSender.sendSony(0x1FF1, 0x76, 2, 20); rawData[42]: - -1040400 - +2400,- 550 - + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + -1043700 + +2450,- 550 + + 700,- 500 +1250,- 550 +1250,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 - + 650,- 550 + 600,- 600 + 650,- 550 +1250,- 550 + + 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 +1250 -Duration=35400 us +Duration=35450us + + +Send Samsung 8 bit command and 8 bit address +Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first Gap=1048550us Duration=65550us +Send with: IrSender.sendSamsung(0xF1, 0x76, ); +rawData[68]: + -1048550 + +4500,-4400 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1650 + + 550,-1650 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650 +Duration=65550us + Send Samsung 16 bit command and address -Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Duration=69000 us +Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Gap=1063650us Duration=68950us Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: - -1057350 - +4550,-4350 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 +rawData[68]: + -1063650 + +4500,-4400 + + 600,-1650 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 600,-1650 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + 650 -Duration=69000 us +Duration=68950us + Send Samsung48 16 bit command -Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first Duration=95900 us +Protocol=Samsung48 Address=0xFFF1 Command=0x9876 Raw-Data=0x6798 48 bits LSB first Gap=1063500us Duration=95850us Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); -rawData[100]: - -1039600 - +4550,-4400 - + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 +rawData[100]: + -1063500 + +4500,-4400 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600 - + 600,- 550 + 600,- 500 + 650,- 500 + 600,-1650 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 - + 650 -Duration=95900 us + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 + + 600 +Duration=95850us + Send RC5 -Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Duration=23200 us +Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Gap=1080100us Duration=23100us Send with: IrSender.sendRC5(0x11, 0x36, ); -rawData[20]: - -1078850 - + 950,- 850 - +1850,-1700 +1800,- 850 + 950,- 850 + 950,-1700 +rawData[20]: + -1080100 + + 950,- 800 + +1850,-1700 +1850,- 850 + 900,- 850 + 950,-1700 + 950,- 850 + 950,- 800 +1850,-1700 + 950,- 850 - +1850 -Duration=23200 us + +1800 +Duration=23100us + Send RC5X with 7.th MSB of command set -Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Duration=23150 us +Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first Gap=1038950us Duration=23100us Send with: IrSender.sendRC5(0x11, 0x76, ); -rawData[20]: - -1037700 - +1850,-1700 - + 950,- 850 +1800,- 850 + 950,- 800 + 950,-1750 - + 950,- 800 + 950,- 850 +1800,-1750 + 950,- 800 - +1850 -Duration=23150 us +rawData[20]: + -1038950 + +1800,-1700 + + 950,- 850 +1800,- 850 + 950,- 850 + 900,-1750 + + 950,- 850 + 900,- 850 +1850,-1700 + 950,- 850 + +1800 +Duration=23100us + Send RC6 -Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Duration=23300 us +Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Gap=1036250us Duration=23300us Send with: IrSender.sendRC6(0xF1, 0x76, ); -rawData[36]: - -1035050 - +2700,- 800 +rawData[36]: + -1036250 + +2650,- 850 + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850 - +1400,- 350 + 500,- 400 + 500,- 400 + 500,- 850 + +1400,- 400 + 450,- 400 + 500,- 400 + 500,- 850 + 500,- 400 + 500,- 400 + 950,- 850 + 950,- 400 + 500,- 400 + 500,- 850 + 950,- 400 + 500,- 850 + 500 -Duration=23300 us +Duration=23300us + 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 Duration=36800 us +Protocol=RC6A Address=0xF1 Command=0x76 Extra=0x2711 Toggle=1 Raw-Data=0xA711F176 35 bits MSB first Gap=1046300us Duration=36800us Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711); -rawData[58]: - -1045150 - +2700,- 800 - + 500,- 400 + 500,- 450 + 450,- 900 +1350,-1300 - + 950,- 850 + 500,- 400 + 900,- 400 + 500,- 450 - + 450,- 850 + 500,- 400 + 500,- 400 + 950,- 850 - + 500,- 400 + 500,- 400 +1000,- 400 + 450,- 400 - + 500,- 450 + 500,- 400 + 450,- 850 + 500,- 400 - + 500,- 400 +1000,- 800 +1000,- 400 + 450,- 450 +rawData[58]: + -1046300 + +2700,- 850 + + 500,- 350 + 500,- 400 + 500,- 850 +1400,-1300 + + 950,- 800 + 500,- 400 + 950,- 450 + 450,- 400 + + 500,- 850 + 500,- 400 + 500,- 400 + 950,- 850 + + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 450 + + 450,- 450 + 450,- 450 + 500,- 800 + 500,- 400 + + 500,- 400 +1000,- 800 + 950,- 450 + 450,- 450 + 450,- 850 + 950,- 400 + 500,- 850 + 500 -Duration=36800 us +Duration=36800us + 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 -Duration=105700 us -Protocol=Bang&Olufsen Address=0x0 Command=0x0 Raw-Data=0x0 0 bits MSB first +rawData[44]: + -1060200 + + 300,-2800 + + 300,-2850 + 250,-12750 + 250,-2800 + 300,-9000 + + 300,-5950 + 250,-5950 + 250,-5950 + 200,-2900 + + 250,-5950 + 250,-5950 + 250,-9000 + 250,-2900 + + 250,-9050 + 250,-5950 + 250,-5900 + 300,-2850 + + 250,-9000 + 300,-5950 + 250,-2850 + 250,-12100 + + 300 +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=1060200us Duration=6500us - Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode -Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Duration=115000 us +Protocol=Bang&Olufsen Address=0xF1 Command=0x76 Raw-Data=0xF176 16 bits MSB first Gap=12750us Duration=114950us 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 -Duration=115000 us + -12750 + + 250,-2800 + + 300,-9000 + 300,-5950 + 250,-5950 + 250,-5950 + + 200,-2900 + 250,-5950 + 250,-5950 + 250,-9000 + + 250,-2900 + 250,-9050 + 250,-5950 + 250,-5900 + + 300,-2850 + 250,-9000 + 300,-5950 + 250,-2850 + + 250,-12100 + 300 +Duration=114950us + Send MagiQuest -Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Duration=63900 us +Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Gap=1097800us Duration=63950us Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -1089250 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 +rawData[112]: + -1097800 + + 300,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 - + 600,- 550 + 600,- 550 + 350,- 800 + 600,- 550 - + 350,- 750 + 650,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 300,- 850 + 350,- 800 + 650,- 500 - + 650,- 500 + 350,- 800 + 650,- 500 + 650,- 500 - + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 650,- 500 + 350,- 800 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 350,- 800 + 350,- 800 + 650,- 500 + + 650,- 500 + 300,- 850 + 650,- 500 + 650,- 500 + + 650,- 550 + 600,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 - + 350,- 800 + 350,- 800 + 650,- 550 + 300,- 800 - + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 500 + 350,- 850 - + 350,- 750 + 350,- 800 + 650,- 500 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 500 + 650 -Duration=63900 us + + 350,- 800 + 350,- 800 + 650,- 550 + 350,- 800 + + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550 + + 350,- 800 + 600,- 550 + 600,- 550 + 300,- 850 + + 350,- 800 + 350,- 800 + 650,- 500 + 600,- 550 + + 300,- 850 + 650,- 500 + 650,- 500 + 650 +Duration=63950us + Send next protocols with IrSender.write Send JVC -Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first Duration=40400 us +Protocol=JVC Address=0xF1 Command=0x76 Raw-Data=0x76F1 16 bits LSB first Gap=1088550us Duration=40450us Send with: IrSender.sendJVC(0xF1, 0x76, ); -rawData[36]: - -1087300 - +8400,-4100 - + 600,-1500 + 600,- 450 + 600,- 450 + 600,- 450 +rawData[36]: + -1088550 + +8400,-4150 + + 550,-1550 + 550,- 500 + 550,- 500 + 600,- 450 + 600,-1500 + 600,-1500 + 600,-1500 + 600,-1500 - + 600,- 450 + 600,-1500 + 600,-1500 + 600,- 450 - + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 + + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 + + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 + 600 -Duration=40400 us +Duration=40450us + Send LG -Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first Duration=59450 us +Protocol=LG Address=0xF1 Command=0x9876 Raw-Data=0xF19876E 28 bits MSB first Gap=1042750us Duration=59350us Send with: IrSender.sendLG(0xF1, 0x9876, ); -rawData[60]: - -1041500 - +9000,-4150 - + 500,-1550 + 550,-1500 + 550,-1550 + 550,-1500 - + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550 - + 550,-1500 + 550,- 500 + 550,- 500 + 550,-1550 - + 550,-1500 + 550,- 500 + 550,- 500 + 550,- 500 - + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 - + 550,- 500 + 550,-1500 + 550,-1550 + 550,- 500 - + 550,-1500 + 550,-1550 + 500,-1550 + 550,- 500 +rawData[60]: + -1042750 + +8900,-4150 + + 550,-1500 + 550,-1550 + 550,-1500 + 550,-1550 + + 550,- 500 + 550,- 500 + 550,- 500 + 500,-1550 + + 550,-1550 + 500,- 500 + 600,- 500 + 500,-1550 + + 550,-1550 + 550,- 500 + 550,- 500 + 550,- 500 + + 500,- 500 + 600,-1500 + 550,-1500 + 550,-1550 + + 550,- 450 + 600,-1500 + 550,-1550 + 550,- 500 + + 550,-1500 + 550,-1500 + 550,-1550 + 550,- 500 + 550 -Duration=59450 us +Duration=59350us + Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Duration=26800 us +Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Gap=1059500us Duration=26800us Send with: IrSender.sendBoseWave(0x0, 0x76, ); -rawData[36]: - -1058350 +rawData[36]: + -1059500 +1050,-1450 - + 550,- 400 + 600,-1400 + 550,-1400 + 600,- 400 - + 600,-1400 + 550,-1400 + 600,-1400 + 600,- 400 - + 550,-1400 + 600,- 400 + 600,- 400 + 600,-1400 + + 550,- 400 + 600,-1400 + 550,-1400 + 600,- 450 + + 550,-1400 + 550,-1400 + 600,-1400 + 600,- 400 + + 600,-1350 + 600,- 400 + 600,- 400 + 600,-1400 + 550,- 400 + 600,- 400 + 600,- 400 + 600,-1400 + 550 -Duration=26800 us +Duration=26800us + Send FAST -Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Duration=28900 us +Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Gap=1043550us Duration=28950us Send with: IrSender.sendFAST(0x0, 0x76, ); -rawData[36]: - -1042350 +rawData[36]: + -1043550 +2150,-1000 - + 550,- 500 + 600,-1500 + 550,-1550 + 550,- 500 - + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 - + 550,-1550 + 550,- 500 + 550,- 500 + 600,-1500 - + 550,- 500 + 550,- 500 + 600,- 450 + 550,-1550 - + 550 -Duration=28900 us + + 600,- 450 + 600,-1500 + 600,-1500 + 600,- 450 + + 600,-1550 + 550,-1500 + 600,-1500 + 600,- 450 + + 600,-1500 + 600,- 450 + 600,- 450 + 600,-1500 + + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 + + 600 +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]: - -1041550 - + 300,- 500 - + 250,- 500 + 250,- 550 + 200,- 500 + 250,- 550 - + 200,- 500 + 250,- 500 + 250,- 500 + 250,- 500 - + 250,- 500 + 250,- 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 + 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 + 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 + 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 + 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 + 250,- 500 + 250,- 500 - + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 - + 250,- 500 + 250,- 500 + 250 -Duration=149550 us +rawData[400]: + -1042750 + + 250,- 500 + + 300,- 450 + 300,- 500 + 250,- 450 + 300,- 450 + + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 250,- 500 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 + + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 500 + 200,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500 + + 250,- 500 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 250 +Duration=149550us + ERROR: Unknown protocol Stop receiver @@ -697,201 +802,925 @@ 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 Duration=67850 us +Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1220500us Duration=67850us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -1028850 - +8900,-4400 - + 650,- 500 + 650,-1600 + 600,- 500 + 600,- 550 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 650,- 450 + 650,-1600 + 650,-1600 +rawData[68]: + -1220500 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 550 + + 600,-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 + 650,-1600 + 650,- 450 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + 650 -Duration=67850 us +Duration=67850us + -Protocol=NEC2 Address=0xF2 Command=0x87 Repeat gap=67950us Raw-Data=0x78870DF2 32 bits LSB first Duration=67900 us +Protocol=NEC2 Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Repeat Gap=69150us Duration=67800us Send with: IrSender.sendNEC2(0xF2, 0x87, ); -rawData[68]: - -67950 +rawData[68]: + -69150 +8950,-4400 - + 600,- 550 + 600,-1650 + 600,- 500 + 600,- 550 - + 600,-1600 + 600,-1650 + 600,-1650 + 600,-1650 - + 600,-1650 + 600,- 550 + 600,-1600 + 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,-1650 - + 600,- 500 + 600,- 550 + 600,- 500 + 600,-1650 - + 600,-1650 + 650,-1600 + 650,-1600 + 600,- 500 - + 650 -Duration=67900 us + + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,- 500 + 650,- 550 + 600,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550 + + 600,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,- 550 + 600,- 500 + 600,- 500 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=67800us + Send NEC with 16 bit address -Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Duration=67800 us +Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1062250us Duration=67850us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -1062200 +rawData[68]: + -1062250 +8950,-4400 - + 600,- 500 + 650,-1600 + 650,- 450 + 650,- 500 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + 650 -Duration=67800 us +Duration=67850us + Send NEC2 with 16 bit address -Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Duration=67850 us +Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1061850us Duration=67800us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -1060650 +rawData[68]: + -1061850 +8950,-4400 - + 650,- 500 + 600,-1650 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,- 500 + 650,-1600 + 600,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,-1650 + 600,- 500 + 600,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 600,-1650 + 600,- 500 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 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 + 650 -Duration=67850 us +Duration=67800us + Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Duration=62250 us +Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Gap=1062500us Duration=62200us Send with: IrSender.sendOnkyo(0xF2, 0x8887, ); -rawData[68]: - -1061250 - +8950,-4400 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 450 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,- 500 + 650,- 500 + 650,- 450 + 650,-1600 - + 650,- 500 + 650,- 450 + 650,- 500 + 650,-1600 +rawData[68]: + -1062500 + +8900,-4450 + + 600,- 500 + 650,-1600 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 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,- 500 + 650,- 450 + 650,- 500 + 600,-1650 + 600 -Duration=62250 us +Duration=62200us + Send Apple -Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Duration=71150 us +Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Gap=1060900us Duration=71150us Send with: IrSender.sendApple(0xF2, 0x87, ); -rawData[68]: - -1059700 +rawData[68]: + -1060900 +8950,-4400 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1550 - + 650,- 500 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 550 + 600,-1600 + + 650,- 500 + 600,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + 650 -Duration=71150 us +Duration=71150us + Send Panasonic -Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first Duration=59250 us +Protocol=Panasonic Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first Gap=1061050us Duration=59350us Send with: IrSender.sendPanasonic(0xF2, 0x87, ); -rawData[100]: - -1059850 - +3500,-1650 +rawData[100]: + -1061050 + +3500,-1700 + + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 350 + 500,- 400 + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,- 350 + 500,- 400 + 500,- 350 + 500,-1250 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,-1250 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1200 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 450 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 500,-1200 + + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 + 500 -Duration=59250 us +Duration=59350us + Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F23 48 bits LSB first Duration=66200 us +Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F23 48 bits LSB first Gap=1081050us Duration=66150us Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711); -rawData[100]: - -1079850 +rawData[100]: + -1081050 +3450,-1700 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 400 - + 450,-1250 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,-1250 + 450,- 400 + 450,- 400 + 500,- 400 + + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400 + 450,-1250 + 500,- 350 - + 500,-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 + 450,-1250 - + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 - + 500,- 400 + 450,-1250 + 500,- 350 + 500,-1250 + + 500,-1250 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,-1250 + 500,-1200 + 500,-1250 + 500,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1200 + + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 + 500 -Duration=66200 us +Duration=66150us + Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first Duration=62750 us +Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first Gap=1081850us Duration=62700us Send with: IrSender.sendKaseikyo_Denon(0xF2, 0x87, ); -rawData[100]: - -1080600 - +3500,-1650 - + 500,- 350 + 500,- 400 + 500,-1200 + 500,- 400 - + 450,-1250 + 500,- 350 + 500,-1250 + 500,- 350 - + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 - + 500,- 350 + 500,- 350 + 500,- 400 + 500,- 350 +rawData[100]: + -1081850 + +3450,-1700 + + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 + + 500,-1250 + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 400 + 450,-1250 + 500,- 350 + 500,- 400 - + 450,-1250 + 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 + 450,-1250 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 - + 450,- 400 + 500,-1250 + 450,- 400 + 500,-1200 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400 + + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,- 350 + 500,-1250 + + 450,- 400 + 500,- 400 + 450,- 400 + 500,-1250 + + 450,- 400 + 500,-1200 + 500,- 400 + 450,-1250 + 500 -Duration=62750 us +Duration=62700us + Send Denon -Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first Duration=22150 us +Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first Gap=1079550us Duration=22150us Send with: IrSender.sendDenon(0x12, 0x87, ); -rawData[32]: - -1078350 +rawData[32]: + -1079550 + 350,- 700 + 300,-1750 + 350,- 700 + 350,- 700 + 350,-1700 + 350,-1750 + 300,-1750 + 350,-1750 - + 300,- 750 + 300,- 700 + 350,- 700 + 350,- 700 + + 300,- 700 + 350,- 700 + 300,- 750 + 350,- 700 + 300,-1750 + 350,- 700 + 350,- 700 + 350 -Duration=22150 us +Duration=22150us + Send Denon/Sharp variant -Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x30F2 15 bits LSB first Duration=23200 us +Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x30F2 15 bits LSB first Gap=1022100us Duration=23150us Send with: IrSender.sendDenon(0x12, 0x87, ); -rawData[32]: - -1020850 - + 350,- 700 + 350,-1750 + 300,- 700 + 350,- 700 - + 350,-1750 + 300,-1750 + 350,-1700 + 350,-1750 - + 300,- 750 + 300,- 750 + 300,- 700 + 350,- 700 - + 350,-1750 + 300,-1750 + 350,- 700 + 350 -Duration=23200 us +rawData[32]: + -1022100 + + 300,- 700 + 350,-1750 + 300,- 750 + 300,- 750 + + 300,-1750 + 300,-1750 + 350,-1750 + 300,-1750 + + 300,- 750 + 350,- 700 + 300,- 750 + 300,- 750 + + 300,-1750 + 350,-1700 + 350,- 700 + 350 +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 Duration=19850 us +Protocol=Sony Address=0x12 Command=0x7 Raw-Data=0x907 12 bits LSB first Gap=1024150us Duration=19800us Send with: IrSender.sendSony(0x12, 0x7, 2, 12); -rawData[26]: - -1022950 +rawData[26]: + -1024150 + +2450,- 550 + +1250,- 550 +1250,- 550 +1250,- 500 + 700,- 500 + + 650,- 550 + 700,- 500 + 650,- 550 + 650,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +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=1039800us Duration=25250us +Send with: IrSender.sendSony(0xF2, 0x7, 2, 15); +rawData[32]: + -1039800 +2450,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +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=1043550us Duration=31250us +Send with: IrSender.sendSony(0xF2, 0x7, 2, 20); +rawData[42]: + -1043550 + +2450,- 550 + +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550 + + 650,- 550 + 650,- 550 + 650,- 550 + 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=1047950us Duration=65650us +Send with: IrSender.sendSamsung(0xF2, 0x87, ); +rawData[68]: + -1047950 + +4500,-4400 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 500 + + 650 +Duration=65650us + + +Send Samsung 16 bit command and address +Protocol=Samsung Address=0xF2 Command=0xA987 Raw-Data=0xA98700F2 32 bits LSB first Gap=1063650us Duration=60050us +Send with: IrSender.sendSamsung(0xF2, 0xA987, ); +rawData[68]: + -1063650 + +4500,-4400 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 650,- 450 + 650,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1650 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,- 500 + 650,-1600 + + 600 +Duration=60050us + + +Send Samsung48 16 bit command +Protocol=Samsung48 Address=0xF2 Command=0xA987 Raw-Data=0x56A9 48 bits LSB first Gap=1063100us Duration=87050us +Send with: IrSender.sendSamsung48(0xF2, 0xA987, ); +rawData[100]: + -1063100 + +4500,-4400 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,- 500 + 600,- 550 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 550 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,- 500 + 600,-1600 + + 650,- 500 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,-1600 + 600,- 500 + 650,-1600 + 650,- 500 + + 650 +Duration=87050us + + +Send RC5 +Protocol=RC5 Address=0x12 Command=0x7 Raw-Data=0x1487 13 bits MSB first Gap=1079600us Duration=24000us +Send with: IrSender.sendRC5(0x12, 0x7, ); +rawData[22]: + -1079600 + + 900,- 850 + +1850,-1700 +1850,- 800 + 950,-1750 +1800,- 850 + + 950,- 800 + 950,- 850 + 900,-1750 + 950,- 850 + + 900,- 850 + 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=1038900us Duration=24050us +Send with: IrSender.sendRC5(0x12, 0x47, ); +rawData[22]: + -1038900 + +1850,-1700 + + 950,- 850 +1800,- 850 + 900,-1750 +1850,- 800 + + 950,- 850 + 950,- 850 + 900,-1750 + 900,- 850 + + 950,- 850 + 950 +Duration=24050us + + +Send RC6 +Protocol=RC6 Address=0xF2 Command=0x87 Toggle=1 Raw-Data=0x1F287 20 bits MSB first Gap=1036350us Duration=22850us +Send with: IrSender.sendRC6(0xF2, 0x87, ); +rawData[36]: + -1036350 + +2700,- 850 + + 500,- 800 + 500,- 400 + 500,- 400 +1400,- 850 + + 500,- 400 + 450,- 400 + 500,- 400 + 500,- 850 + + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400 + + 500,- 400 + 500,- 400 + 950,- 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=1047550us Duration=36350us +Send with: IrSender.sendRC6A(0xF2, 0x87, , 0x2711); +rawData[60]: + -1047550 + +2650,- 900 + + 500,- 400 + 500,- 400 + 450,- 850 + 500,- 850 + + 950,- 400 + 950,- 850 + 450,- 400 + 950,- 450 + + 450,- 450 + 450,- 850 + 500,- 400 + 500,- 400 + + 950,- 850 + 500,- 400 + 500,- 400 + 950,- 400 + + 500,- 450 + 450,- 450 + 450,- 400 + 500,- 850 + + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400 + + 500,- 400 + 500,- 400 +1000,- 350 + 500,- 400 + + 500 +Duration=36350us + + +Send Bang&Olufsen +- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled +rawData[44]: + -1061100 + + 200,-2850 + + 250,-2850 + 250,-12750 + 250,-2850 + 250,-9050 + + 250,-5950 + 300,-5900 + 300,-5950 + 250,-2850 + + 250,-5950 + 250,-9000 + 300,-2850 + 250,-9050 + + 250,-2850 + 250,-5950 + 250,-5950 + 250,-5900 + + 300,-9050 + 250,-5900 + 300,-5950 + 250,-12100 + + 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=1061100us 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,-9050 + 250,-5950 + 300,-5900 + 300,-5950 + + 250,-2850 + 250,-5950 + 250,-9000 + 300,-2850 + + 250,-9050 + 250,-2850 + 250,-5950 + 250,-5950 + + 250,-5900 + 300,-9050 + 250,-5900 + 300,-5950 + + 250,-12100 + 250 +Duration=118050us + + +Send MagiQuest +Protocol=MagiQuest Address=0xF2 Command=0x187 Raw-Data=0x6BCD00F2 56 bits MSB first Gap=1097800us Duration=63700us +Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, ); +rawData[112]: + -1097800 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 + + 650,- 500 + 650,- 500 + 350,- 800 + 650,- 500 + + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 + + 650,- 500 + 350,- 800 + 350,- 800 + 650,- 500 + + 600,- 550 + 350,- 800 + 650,- 500 + 350,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 + + 300,- 800 + 350,- 800 + 350,- 800 + 650,- 500 + + 650,- 500 + 650,- 550 + 600,- 550 + 300,- 800 + + 350,- 800 + 650,- 550 + 300,- 850 + 600,- 550 + + 600,- 550 + 350,- 800 + 350,- 750 + 350,- 850 + + 300,- 800 + 650,- 500 + 650,- 500 + 650,- 550 + + 350,- 800 + 350,- 800 + 650,- 500 + 350,- 800 + + 350,- 800 + 350,- 800 + 650,- 500 + 350 +Duration=63700us + + +Send next protocols with IrSender.write + +Send JVC +Protocol=JVC Address=0xF2 Command=0x87 Raw-Data=0x87F2 16 bits LSB first Gap=1088850us Duration=39350us +Send with: IrSender.sendJVC(0xF2, 0x87, ); +rawData[36]: + -1088850 + +8400,-4150 + + 550,- 500 + 600,-1500 + 550,- 500 + 550,- 500 + + 600,-1500 + 600,-1500 + 550,-1550 + 550,-1500 + + 600,-1550 + 550,-1500 + 600,-1500 + 600,- 450 + + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 + + 600 +Duration=39350us + + +Send LG +Protocol=LG Address=0xF2 Command=0xA987 Raw-Data=0xF2A9872 28 bits MSB first Gap=1042700us Duration=57350us +Send with: IrSender.sendLG(0xF2, 0xA987, ); +rawData[60]: + -1042700 + +8950,-4100 + + 550,-1550 + 550,-1500 + 550,-1550 + 550,-1500 + + 550,- 500 + 550,- 500 + 550,-1550 + 550,- 500 + + 550,-1500 + 550,- 500 + 550,-1550 + 550,- 500 + + 550,-1500 + 550,- 500 + 550,- 500 + 550,-1550 + + 550,-1500 + 550,- 500 + 550,- 500 + 550,- 500 + + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 + + 550,- 500 + 550,- 500 + 550,-1500 + 550,- 500 + + 550 +Duration=57350us + + +Send Bosewave with no address and 8 command bits +Protocol=BoseWave Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first Gap=1059500us Duration=26800us +Send with: IrSender.sendBoseWave(0x0, 0x87, ); +rawData[36]: + -1059500 + +1050,-1450 + + 550,-1400 + 600,-1400 + 600,-1400 + 550,- 400 + + 600,- 400 + 550,- 450 + 600,- 400 + 600,-1350 + + 600,- 400 + 550,- 450 + 600,- 400 + 550,-1400 + + 600,-1400 + 550,-1400 + 600,-1450 + 550,- 400 + + 550 +Duration=26800us + + +Send FAST +Protocol=FAST Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first Gap=1043550us Duration=28950us +Send with: IrSender.sendFAST(0x0, 0x87, ); +rawData[36]: + -1043550 + +2150,-1000 + + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 + + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 + + 600,- 450 + 600,- 450 + 550,- 500 + 600,-1500 + + 600,-1500 + 600,-1500 + 550,-1550 + 600,- 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]: + -1042650 + + 250,- 500 + + 300,- 450 + 300,- 550 + 200,- 500 + 250,- 550 + + 250,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 250,- 500 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 250,- 500 + 300,- 450 + 300,- 450 + + 300,- 500 + 250,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 + + 250,- 500 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450 + + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500 + + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500 + + 250,- 500 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 250,- 550 + 250,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 + + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 + + 300,- 450 + 250,- 500 + 300 +Duration=149600us + +ERROR: Unknown protocol + +Stop receiver +Start receiver + +address=0x1F3 command=0x98 + +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=1220600us Duration=67800us +Send with: IrSender.sendNEC(0xF3, 0x98, ); +rawData[68]: + -1220600 + +8950,-4400 + + 600,-1600 + 650,-1650 + 600,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,- 500 + 650,- 450 + 650,- 500 + 600,-1650 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=67800us + + +Protocol=NEC2 Address=0xF3 Command=0x98 Raw-Data=0x67980CF3 32 bits LSB first Repeat Gap=69200us Duration=67800us +Send with: IrSender.sendNEC2(0xF3, 0x98, ); +rawData[68]: + -69200 + +8950,-4350 + + 650,-1600 + 650,-1600 + 650,- 450 + 650,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 550 + + 600,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=67800us + + +Protocol=NEC2 Address=0xF3 Command=0x98 Raw-Data=0x67980CF3 32 bits LSB first Repeat Gap=69650us Duration=67750us +Send with: IrSender.sendNEC2(0xF3, 0x98, ); +rawData[68]: + -69650 + +8900,-4400 + + 650,-1650 + 600,-1600 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,-1650 + 600,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=67750us + + +Send NEC with 16 bit address +Protocol=NEC Address=0x1F3 Command=0x98 Raw-Data=0x679801F3 32 bits LSB first Gap=1062250us Duration=66650us +Send with: IrSender.sendNEC(0x1F3, 0x98, ); +rawData[68]: + -1062250 + +8950,-4400 + + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 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 + 600,-1650 + 600,- 500 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=66650us + + +Send NEC2 with 16 bit address +Protocol=NEC Address=0x1F3 Command=0x98 Raw-Data=0x679801F3 32 bits LSB first Gap=1062050us Duration=66700us +Send with: IrSender.sendNEC(0x1F3, 0x98, ); +rawData[68]: + -1062050 + +8950,-4400 + + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,-1600 + 600,-1650 + 600,- 500 + + 650 +Duration=66700us + + +Send Onkyo (NEC with 16 bit command) +Protocol=Onkyo Address=0x1F3 Command=0x9998 Raw-Data=0x999801F3 32 bits LSB first Gap=1062650us Duration=65600us +Send with: IrSender.sendOnkyo(0x1F3, 0x9998, ); +rawData[68]: + -1062650 + +8950,-4400 + + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 550 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 550 + 600,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 600,- 600 + 600,-1600 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650 +Duration=65600us + + +Send Apple +Protocol=Apple Address=0xF3 Command=0x98 Raw-Data=0xF39887EE 32 bits LSB first Gap=1061100us Duration=71150us +Send with: IrSender.sendApple(0xF3, 0x98, ); +rawData[68]: + -1061100 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1650 + + 600,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1650 + 600,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600 +Duration=71150us + + +Send Panasonic +Protocol=Panasonic Address=0x1F3 Command=0x98 Raw-Data=0xB7981F30 48 bits LSB first Gap=1061050us Duration=62750us +Send with: IrSender.sendPanasonic(0x1F3, 0x98, ); +rawData[100]: + -1061050 + +3500,-1700 + + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 350 + + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 + + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,-1250 + + 450,-1250 + 500,- 350 + 500,- 400 + 450,-1250 + + 500,-1250 + 450,-1250 + 500,-1200 + 500,- 400 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1200 + + 500 +Duration=62750us + + +Send Kaseikyo with 0x4711 as Vendor ID +Protocol=Kaseikyo Address=0x1F3 Command=0x98 Extra=0x4711 Raw-Data=0xB4981F33 48 bits LSB first Gap=1081300us Duration=66100us +Send with: IrSender.sendKaseikyo(0x1F3, 0x98, , 0x4711); +rawData[100]: + -1081300 + +3450,-1700 + + 450,-1250 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,-1250 + 450,- 400 + 500,- 400 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,-1250 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,-1250 + 500,- 350 + 450,- 400 + + 500,-1250 + 450,-1250 + 450,- 450 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 + + 450,-1250 + 500,- 350 + 500,- 400 + 450,- 450 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,-1250 + + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 + + 450,- 400 + 500,- 350 + 500,-1250 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 + + 500 +Duration=66100us + + +Send Kaseikyo_Denon variant +Protocol=Kaseikyo_Denon Address=0x1F3 Command=0x98 Raw-Data=0xB7981F30 48 bits LSB first Gap=1082000us Duration=66150us +Send with: IrSender.sendKaseikyo_Denon(0x1F3, 0x98, ); +rawData[100]: + -1082000 + +3500,-1650 + + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,- 400 + 450,-1250 + 500,- 400 + + 450,- 400 + 500,-1200 + 500,- 400 + 450,- 400 + + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 + + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1250 + + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 500,-1200 + + 500,-1250 + 450,- 400 + 500,- 400 + 500,-1200 + + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 + + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1250 + + 450 +Duration=66150us + + +Send Denon +Protocol=Denon Address=0x13 Command=0x98 Raw-Data=0x1313 15 bits LSB first Gap=1079800us Duration=22100us +Send with: IrSender.sendDenon(0x13, 0x98, ); +rawData[32]: + -1079800 + + 300,-1750 + 350,-1750 + 300,- 750 + 300,- 700 + + 350,-1750 + 300,- 750 + 300,- 700 + 350,- 700 + + 350,-1750 + 300,-1750 + 300,- 750 + 300,- 750 + + 300,-1750 + 350,- 700 + 350,- 700 + 300 +Duration=22100us + + +Send Denon/Sharp variant +Protocol=Denon Address=0x13 Command=0x98 Raw-Data=0x3313 15 bits LSB first Gap=1022100us Duration=23100us +Send with: IrSender.sendDenon(0x13, 0x98, ); +rawData[32]: + -1022100 + + 300,-1750 + 300,-1750 + 350,- 700 + 350,- 700 + + 350,-1700 + 350,- 700 + 350,- 700 + 350,- 700 + + 300,-1750 + 350,-1750 + 300,- 700 + 350,- 700 + + 350,-1750 + 300,-1750 + 350,- 750 + 250 +Duration=23100us + + +Send Sony/SIRCS with 7 command and 5 address bits +Protocol=Sony Address=0x13 Command=0x18 Raw-Data=0x998 12 bits LSB first Gap=1024150us Duration=19850us +Send with: IrSender.sendSony(0x13, 0x18, 2, 12); +rawData[26]: + -1024150 + +2450,- 550 + + 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 +1250 -Duration=19850 us +Duration=19850us + +Send Sony/SIRCS with 7 command and 8 address bits +Protocol=Sony Address=0xF3 Command=0x18 Raw-Data=0x7998 15 bits LSB first Gap=1040000us Duration=25200us +Send with: IrSender.sendSony(0xF3, 0x18, 2, 15); +rawData[32]: + -1040000 + +2400,- 550 + + 700,- 500 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 +1250,- 550 +1250 +Duration=25200us + + +Send Sony/SIRCS with 7 command and 13 address bits +Protocol=Sony Address=0x1F3 Command=0x18 Raw-Data=0xF998 20 bits LSB first Gap=1043700us Duration=31850us +Send with: IrSender.sendSony(0x1F3, 0x18, 2, 20); +rawData[42]: + -1043700 + +2450,- 550 + + 650,- 550 + 700,- 500 + 650,- 550 +1250,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + +1250,- 550 +1250,- 550 +1300,- 500 +1250,- 550 + + 650,- 550 + 650,- 550 + 650,- 550 + 650 +Duration=31850us + + +Send Samsung 8 bit command and 8 bit address +Protocol=Samsung Address=0xF3 Command=0x98 Raw-Data=0x6798F3F3 32 bits LSB first Gap=1048300us Duration=67800us +Send with: IrSender.sendSamsung(0xF3, 0x98, ); +rawData[68]: + -1048300 + +4450,-4400 + + 650,-1600 + 650,-1600 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,- 450 + 650,- 500 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,-1650 + 600,-1600 + 650,- 500 + + 600 +Duration=67800us + + +Send Samsung 16 bit command and address +Protocol=Samsung Address=0x1F3 Command=0xBA98 Raw-Data=0xBA9801F3 32 bits LSB first Gap=1063700us Duration=62250us +Send with: IrSender.sendSamsung(0x1F3, 0xBA98, ); +rawData[68]: + -1063700 + +4500,-4400 + + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,- 500 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,- 500 + 600,-1600 + + 650 +Duration=62250us + + +Send Samsung48 16 bit command +Protocol=Samsung48 Address=0x1F3 Command=0xBA98 Raw-Data=0x45BA 48 bits LSB first Gap=1063250us Duration=89200us +Send with: IrSender.sendSamsung48(0x1F3, 0xBA98, ); +rawData[100]: + -1063250 + +4500,-4400 + + 650,-1600 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 550 + 600,- 500 + 600,-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 + + 650,- 500 + 600,-1600 + 650,- 500 + 600,-1650 + + 600,-1600 + 650,-1600 + 650,- 500 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,-1600 + 650,- 500 + + 600 +Duration=89200us + + +Send RC5 +Protocol=RC5 Address=0x13 Command=0x18 Toggle=1 Raw-Data=0x1CD8 13 bits MSB first Gap=1079850us Duration=23100us +Send with: IrSender.sendRC5(0x13, 0x18, ); +rawData[22]: + -1079850 + + 950,- 800 + + 950,- 850 + 900,- 850 +1850,- 850 + 900,-1750 + + 950,- 850 +1800,-1700 + 950,- 850 +1800,- 850 + + 950,- 800 + 950 +Duration=23100us + + +Send RC5X with 7.th MSB of command set +Protocol=RC5 Address=0x13 Command=0x58 Raw-Data=0x4D8 13 bits MSB first Gap=1040700us Duration=23100us +Send with: IrSender.sendRC5(0x13, 0x58, ); +rawData[20]: + -1040700 + +1800,- 850 + + 950,-1700 +1850,- 800 + 950,-1750 + 900,- 850 + +1850,-1700 + 950,- 850 +1800,- 850 + 900,- 850 + + 950 +Duration=23100us + + +Send RC6 +Protocol=RC6 Address=0xF3 Command=0x98 Raw-Data=0xF398 20 bits MSB first Gap=1035450us Duration=23300us +Send with: IrSender.sendRC6(0xF3, 0x98, ); +rawData[38]: + -1035450 + +2700,- 850 + + 500,- 800 + 500,- 400 + 500,- 400 + 500,- 850 + +1400,- 400 + 450,- 400 + 500,- 400 + 500,- 850 + + 500,- 400 + 950,- 400 + 500,- 400 + 500,- 850 + + 500,- 400 + 950,- 400 + 500,- 850 + 500,- 400 + + 500,- 400 + 500 +Duration=23300us + + +Send RC6A with 14 bit 0x2711 as extra +Protocol=RC6A Address=0xF3 Command=0x98 Extra=0x2711 Toggle=1 Raw-Data=0xA711F398 35 bits MSB first Gap=1047300us Duration=36800us +Send with: IrSender.sendRC6A(0xF3, 0x98, , 0x2711); +rawData[60]: + -1047300 + +2700,- 850 + + 500,- 400 + 450,- 450 + 500,- 800 +1400,-1300 + + 950,- 850 + 500,- 400 + 950,- 400 + 450,- 400 + + 500,- 900 + 450,- 400 + 500,- 400 + 950,- 850 + + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 450 + + 450,- 450 + 450,- 450 + 450,- 850 + 500,- 400 + + 950,- 450 + 450,- 450 + 450,- 850 + 500,- 400 + + 950,- 400 + 500,- 850 + 500,- 400 + 500,- 400 + + 500 +Duration=36800us + + +Send Bang&Olufsen +- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled +rawData[44]: + -1061400 + + 300,-2800 + + 250,-2850 + 250,-12750 + 300,-2850 + 200,-9050 + + 300,-5950 + 250,-5950 + 250,-5950 + 250,-2850 + + 250,-5950 + 250,-9000 + 300,-5950 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-9050 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-5950 + 250,-12100 + + 300 +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=1061400us 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=0xF3 Command=0x98 Raw-Data=0xF398 16 bits MSB first Gap=12750us Duration=115000us +Send with: IrSender.sendBang&Olufsen(0xF3, 0x98, ); +rawData[38]: + -12750 + + 300,-2850 + + 200,-9050 + 300,-5950 + 250,-5950 + 250,-5950 + + 250,-2850 + 250,-5950 + 250,-9000 + 300,-5950 + + 250,-5950 + 250,-2850 + 250,-5950 + 250,-9050 + + 250,-5950 + 250,-2850 + 250,-5950 + 250,-5950 + + 250,-12100 + 300 +Duration=115000us diff --git a/examples/UnitTest/UnitTest_64bit.log b/examples/UnitTest/UnitTest_64bit.log index 7def9abbc..82e257d33 100644 --- a/examples/UnitTest/UnitTest_64bit.log +++ b/examples/UnitTest/UnitTest_64bit.log @@ -1,648 +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 - +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 + -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 +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]: - -1032900 - +2650,- 900 - + 450,- 450 + 450,- 450 + 450,- 850 +1400,-1300 - + 950,- 850 + 500,- 400 + 950,- 400 + 500,- 450 - + 450,- 850 + 500,- 400 + 500,- 400 + 950,- 850 - + 500,- 400 + 500,- 400 + 950,- 450 + 450,- 450 - + 450,- 450 + 450,- 400 + 500,- 850 + 500,- 400 + -1067100 + +2750,- 800 + + 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,- 450 + 450,- 850 + 500 -Sum: 36850 + + 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 @@ -678,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/src/IRReceive.hpp b/src/IRReceive.hpp index bf13923ca..13cde569a 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -139,11 +139,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; } /* @@ -152,13 +154,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 @@ -170,14 +173,14 @@ void IRReceiveTimerInterruptHandler() { // 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 = irparams.TickCounterForISR; + 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) { + } else if (tStateForISR == IR_REC_STATE_MARK) { // Timing mark here, rawlen is even if (tIRInputLevel != INPUT_MARK) { /* @@ -186,17 +189,22 @@ 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) { + } else if (tStateForISR == IR_REC_STATE_SPACE) { /* * In space receiving here, rawlen is odd * Check for timeout or overflow */ - if (irparams.TickCounterForISR > RECORD_GAP_TICKS || irparams.rawlen >= RAW_BUFFER_LENGTH - 1) { + 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; @@ -235,11 +243,16 @@ 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 space +#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 @@ -1182,14 +1195,16 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM) { // Check header "mark" and "space" - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { + if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], + pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { #if defined(LOCAL_TRACE) Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header mark length is wrong")); #endif return false; } - if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { + if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], + pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { #if defined(LOCAL_TRACE) Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header space length is wrong")); @@ -1428,7 +1443,7 @@ void printActiveIRProtocols(Print *aSerial) { * 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) { +bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) { // DEPRECATED (void) aPrintRepeatGap; return printIRResultShort(aSerial, aCheckForRecordGapsMicros); diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index f399741f6..76811e9ce 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. /* @@ -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) + if ((matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_IR_MARK_FOR_DECODE) || 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_IR_MARK_FOR_DECODE) || matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_DATALINK_MARK))) { - BEO_TRACE_PRINT(::getProtocolString(BANG_OLUFSEN)); BEO_TRACE_PRINTLN(F("B&O: AGC only part (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(decodedIRData.rawDataPtr->rawbuf[1], 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(decodedIRData.rawDataPtr->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; } @@ -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_MagiQuest.hpp b/src/ir_MagiQuest.hpp index 735995263..f2d8fa08a 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -191,10 +191,6 @@ bool IRrecv::decodeMagiQuest() { 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]; From 01166327597dc4c277d1c6b7a828bc624a972e1e Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 18 Jul 2025 10:37:39 +0200 Subject: [PATCH 088/133] fixed inconsistent ESP_ARDUINO_VERSION_VAL handling --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 ++- README.md | 2 +- src/private/IRTimer.hpp | 22 +++++++++++++--------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index eb97d831e..50f11ec68 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -16,9 +16,10 @@ body: 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.** + Without the FQBN we are most likely not able to fix the the issue. validations: required: true diff --git a/README.md b/README.md index f9860b22a..ee0cffe43 100644 --- a/README.md +++ b/README.md @@ -967,7 +967,7 @@ Digispark boards are only tested with [ATTinyCore](https://github.com/SpenceKond - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD (Zero, MKR*, **but not DUE, the latter is SAM architecture**) - ESP8266 -- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif) +- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif). 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 diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index be3c50c41..ac893cc1d 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -11,7 +11,7 @@ ************************************************************************************* * MIT License * - * Copyright (c) 2021-2023 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 @@ -1606,13 +1606,13 @@ hw_timer_t *s50usTimer = nullptr; // set by timerConfigForReceive() #define _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE 255 //# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) && !defined(SEND_LEDC_CHANNEL) -# if ESP_ARDUINO_VERSION < (3 << 16 + 0 >> 8 + 0) && !defined(SEND_LEDC_CHANNEL) +# if ESP_ARDUINO_VERSION < (3 << 16 | 0 << 8 | 0) && !defined(SEND_LEDC_CHANNEL) // works also in case ESP_ARDUINO_VERSION_VAL is not defined #define SEND_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels # endif void timerEnableReceiveInterrupt() { //# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) -# if ESP_ARDUINO_VERSION >= (3 << 16 + 0 >> 8 + 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) timerStart(s50usTimer); # else timerAlarmEnable(s50usTimer); @@ -1620,7 +1620,7 @@ void timerEnableReceiveInterrupt() { } //# if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 2) -# if ESP_ARDUINO_VERSION < (2 << 16 + 0 >> 8 + 2) +# if ESP_ARDUINO_VERSION < (2 << 16 | 0 << 8 | 2) /* * Special support for ESP core < 202 */ @@ -1635,7 +1635,7 @@ void timerDisableReceiveInterrupt() { void timerDisableReceiveInterrupt() { if (s50usTimer != nullptr) { //# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) -# if ESP_ARDUINO_VERSION >= (3 << 16 + 0 >> 8 + 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) timerStop(s50usTimer); # else timerAlarmDisable(s50usTimer); @@ -1655,7 +1655,8 @@ void timerConfigForReceive() { // simply call the readable API versions :) // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true if (s50usTimer == nullptr) { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) s50usTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. timerStop(s50usTimer); // Stop it here, to avoid "error E (3447) gptimer: gptimer_start(348): timer is not enabled yet" at timerEnableReceiveInterrupt() timerAttachInterrupt(s50usTimer, &IRReceiveTimerInterruptHandler); @@ -1674,7 +1675,8 @@ uint8_t sLastSendPin = 0; // Avoid multiple attach() or if pin changes, detach b # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) # if defined(IR_SEND_PIN) ledcWrite(IR_SEND_PIN, (IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH * _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE) / 100); // 3.x API # else @@ -1686,7 +1688,8 @@ void enableSendPWMByTimer() { # endif } void disableSendPWMByTimer() { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) # if defined(IR_SEND_PIN) # if defined(USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN) ledcWrite(IR_SEND_PIN, _IRREMOTE_ESP32_LEDC_RESOLUTION_MAX_PWM_VALUE); // 3.x API @@ -1711,7 +1714,8 @@ void disableSendPWMByTimer() { * ledcWrite since ESP 2.0.2 does not work if pin mode is set. */ void timerConfigForSend(uint16_t aFrequencyKHz) { -# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +//# if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) +# if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) # if defined(IR_SEND_PIN) if(sLastSendPin == 0){ ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API From 5712e517e505ba623962f45cda010d88b372640b Mon Sep 17 00:00:00 2001 From: Armin Date: Fri, 18 Jul 2025 22:05:42 +0200 Subject: [PATCH 089/133] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 50f11ec68..56e71e9f3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -14,7 +14,7 @@ body: - type: input id: Board_FQBN attributes: - label: Please specify **FQBN** (Fully Qualified Board Name). + 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. @@ -27,7 +27,6 @@ body: id: Exotic_core_URL attributes: label: The board manager URL used for exotic cores. - value: "https://" validations: required: false @@ -105,7 +104,7 @@ body: 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 @@ -203,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! From e7b81bec52ac1a819d1c43ba42deecb420467c47 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 28 Jul 2025 14:38:51 +0200 Subject: [PATCH 090/133] Support for multiple instances --- README.md | 2 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 +- examples/MicroGirs/MicroGirs.ino | 4 +- .../MultipleReceivers/MultipleReceivers.ino | 147 +++++++ .../MultipleReceivers/PinDefinitionsAndMore.h | 359 ++++++++++++++++++ examples/ReceiveAndSend/ReceiveAndSend.ino | 8 +- examples/UnitTest/UnitTest.ino | 10 +- src/IRProtocol.h | 4 +- src/IRProtocol.hpp | 16 +- src/IRReceive.hpp | 183 +++++++-- src/IRremoteInt.h | 15 +- src/ir_BangOlufsen.hpp | 16 +- src/ir_BoseWave.hpp | 2 +- src/ir_Denon.hpp | 2 +- src/ir_DistanceWidthProtocol.hpp | 12 +- src/ir_JVC.hpp | 4 +- src/ir_LG.hpp | 10 +- src/ir_Lego.hpp | 4 +- src/ir_NEC.hpp | 8 +- src/ir_Pronto.hpp | 4 +- src/ir_RC5_RC6.hpp | 4 +- src/ir_Template.hpp | 2 +- 22 files changed, 719 insertions(+), 99 deletions(-) create mode 100644 examples/MultipleReceivers/MultipleReceivers.ino create mode 100644 examples/MultipleReceivers/PinDefinitionsAndMore.h diff --git a/README.md b/README.md index ee0cffe43..1c16c6615 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ If IR_SEND_PIN is not defined (before the line `#include `) you mu - 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.irparams.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. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index e381293da..48b5f16ed 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -364,7 +364,7 @@ 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 ")); diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index ca2a9b18a..316983ac8 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -258,13 +258,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('-'); diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino new file mode 100644 index 000000000..b35ca00e6 --- /dev/null +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -0,0 +1,147 @@ +/* + * 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 + +/* + * 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 +#define IR_RECEIVE_PIN_OF_SECOND_RECEIVER 5 +void UserIRReceiveTimerInterruptHandler(); // must 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/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 5a0935998..45dc008be 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -185,9 +185,9 @@ void loop() { // 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) { @@ -214,7 +214,7 @@ void storeCode() { 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.decodedIRData.rawDataPtr->rawlen - 1; + sStoredIRData.rawCodeLength = IrReceiver.irparams.rawlen - 1; /* * Store the current raw data in a dedicated array for later usage */ @@ -223,7 +223,7 @@ void storeCode() { * Print info */ Serial.print(F("Received unknown or pulse width/distance code and store ")); - Serial.print(IrReceiver.decodedIRData.rawDataPtr->rawlen - 1); + 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 diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 947b9457e..a99b84b1b 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -821,9 +821,9 @@ void loop() { Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); IrReceiver.printIRResultRawFormatted(&Serial, true); Serial.println(F("- Now try to decode the first 6 entries, which results in rawData 0x0")); - uint8_t tOriginalRawlen = IrReceiver.decodedIRData.rawDataPtr->rawlen; + uint8_t tOriginalRawlen = IrReceiver.irparams.rawlen; IrReceiver.decodedIRData.rawlen = 6; - IrReceiver.decodedIRData.rawDataPtr->rawlen = 6; + IrReceiver.irparams.rawlen = 6; /* * decode first part / AGC part of frame */ @@ -836,11 +836,11 @@ 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.decodedIRData.rawDataPtr->rawbuf[0]; + IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0]; # endif checkReceive(sAddress & 0x0FF, sCommand); delay(DELAY_AFTER_SEND); diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 8f1445891..f7d4cd6dd 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -122,14 +122,12 @@ struct IRData { /* * 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. */ 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 diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index bed8fa7a6..68ee1130f 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -155,19 +155,23 @@ namespace PrintULL { * @{ */ /** - * 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 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; printIRResultShort(aSerial, aIRDataPtr); } +/* + * Only used in example ReceiveAndSend.cpp + */ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) { aSerial->println(F("Overflow")); @@ -256,14 +260,6 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { #if !defined(DISABLE_CODE_FOR_RECEIVER) aSerial->print(F(" Gap=")); aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK); - aSerial->print(F("us")); - - uint16_t tSumOfDurationTicks = 0; - for (IRRawlenType i = 1; i < aIRDataPtr->rawlen; i++) { - tSumOfDurationTicks += aIRDataPtr->rawDataPtr->rawbuf[i]; - } - aSerial->print(F(" Duration=")); - aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); aSerial->println(F("us")); #else aSerial->println(); diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 13cde569a..78d184fb2 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -61,7 +61,7 @@ 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() /** @@ -69,7 +69,6 @@ unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR wi * @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_RECEIVE_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); @@ -77,7 +76,6 @@ IRrecv::IRrecv() { } IRrecv::IRrecv(uint_fast8_t aReceivePin) { - decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc. setReceivePin(aReceivePin); #if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); @@ -90,7 +88,6 @@ 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_RECEIVE_FEEDBACK_CODE) setLEDFeedback(aFeedbackLEDPin, DO_NOT_ENABLE_LED_FEEDBACK); @@ -122,7 +119,8 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { #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 @@ -218,7 +216,7 @@ 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. @@ -277,9 +275,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) @@ -728,13 +739,13 @@ bool IRrecv::decode() { * 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. * - * 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 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 aOneMarkMicros Checked if PULSE_WIDTH * @param aZeroMarkMicros Required for deciding if we have PULSE_DISTANCE. * @param aOneSpaceMicros Checked if PULSE_DISTANCE. @@ -744,7 +755,7 @@ bool IRrecv::decode() { bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) { - auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset]; + auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we check aOneSpaceMicros -> pulse distance protocol @@ -805,7 +816,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) { (void) aZeroSpaceMicros; - 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 IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop @@ -869,7 +880,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) { - auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset]; + auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol @@ -967,8 +978,7 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa 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]) { + if (aZeroSpaceMicros == aOneSpaceMicros && tRawBufPointer < &irparams.rawbuf[irparams.rawlen]) { // Check for constant length space (of pulse width protocol) here if (!matchSpace(tSpaceTicks, aOneSpaceMicros)) { #if defined(LOCAL_DEBUG) @@ -1053,7 +1063,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)) { @@ -1133,7 +1143,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; } @@ -1176,14 +1186,14 @@ 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(decodedIRData.rawDataPtr->rawbuf[2], aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros)) { + 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")); @@ -1195,16 +1205,14 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM) { // Check header "mark" and "space" - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], - pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { + if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { #if defined(LOCAL_TRACE) Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header mark length is wrong")); #endif return false; } - if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], - pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { + if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { #if defined(LOCAL_TRACE) Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); Serial.println(F(": Header space length is wrong")); @@ -1449,8 +1457,113 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aChec 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, DEC); + 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 + */ + 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 + /* + * Print number of bits processed + */ + aSerial->print(' '); + aSerial->print(decodedIRData.numberOfBits, DEC); + 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(' '); + 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, DEC); + aSerial->println(F("us")); +#else + aSerial->println(); +#endif + } + } + // call no class function with same name - ::printIRResultShort(aSerial, &decodedIRData); if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) { return checkForRecordGapsMicros(aSerial); } @@ -1478,7 +1591,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; } @@ -1488,7 +1601,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; } @@ -1508,7 +1621,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; } @@ -1520,7 +1633,7 @@ 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; } @@ -1702,7 +1815,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) { uint16_t tSumOfDurationTicks = 0; for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { - tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i]; + tSumOfDurationTicks += irparams.rawbuf[i]; } aSerial->print(F("Duration=")); if (aOutputMicrosecondsInsteadOfTicks) { @@ -1716,7 +1829,7 @@ void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTi } /** - * 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. @@ -1758,7 +1871,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI 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 { @@ -1809,7 +1922,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI } /** - * 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. @@ -1832,7 +1945,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr // 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 @@ -1880,7 +1993,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; diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 1fe279796..0aeb6d331 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -126,8 +126,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 @@ -194,8 +194,8 @@ 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 }; @@ -206,16 +206,22 @@ 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 @@ -366,6 +372,7 @@ class IRrecv { 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 to fill in JVC, LG, NEC repeat values. Parity for Denon autorepeat diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 76811e9ce..3c1f3015b 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -332,10 +332,10 @@ 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_FOR_DECODE) - || matchMark(decodedIRData.rawDataPtr->rawbuf[3], BEO_DATALINK_MARK)) - && (matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK_FOR_DECODE) - || matchSpace(decodedIRData.rawDataPtr->rawbuf[4], BEO_PULSE_LENGTH_ZERO - BEO_DATALINK_MARK))) { + 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 @@ -351,10 +351,10 @@ bool IRrecv::decodeBangOlufsen() { return false; // no B&O protocol } - if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_IR_MARK_FOR_DECODE)) { + if (matchMark(irparams.rawbuf[1], BEO_IR_MARK_FOR_DECODE)) { # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) protocolMarkLength = BEO_IR_MARK_FOR_DECODE; - } else if (matchMark(decodedIRData.rawDataPtr->rawbuf[1], BEO_DATALINK_MARK)) { + } else if (matchMark(irparams.rawbuf[1], BEO_DATALINK_MARK)) { protocolMarkLength = BEO_DATALINK_MARK; # endif } else { @@ -368,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(' '); diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index 336d886f0..455eb85f7 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -85,7 +85,7 @@ bool IRrecv::decodeBoseWave() { } // 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 bfbe45caa..7e47a2c85 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -188,7 +188,7 @@ bool IRrecv::decodeDenon() { } // Check for stop mark - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[(2 * DENON_BITS) + 1], DENON_HEADER_MARK)) { + 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")); diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 0012625c1..16541aeda 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -224,7 +224,7 @@ 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) { @@ -271,7 +271,7 @@ 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) { @@ -325,9 +325,9 @@ bool IRrecv::decodeDistanceWidth() { */ #if defined(LOCAL_DEBUG) Serial.print(F("DistanceWidthTimingInfoStruct: ")); - Serial.print(decodedIRData.rawDataPtr->rawbuf[1] * MICROS_PER_TICK); + Serial.print(irparams.rawbuf[1] * MICROS_PER_TICK); Serial.print(F(", ")); - Serial.print(decodedIRData.rawDataPtr->rawbuf[2] * MICROS_PER_TICK); + Serial.print(irparams.rawbuf[2] * MICROS_PER_TICK); Serial.print(F(", ")); Serial.print(tMarkTicksLong * MICROS_PER_TICK); Serial.print(F(", ")); @@ -448,8 +448,8 @@ bool IRrecv::decodeDistanceWidth() { /* * 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_JVC.hpp b/src/ir_JVC.hpp index ef69a5986..ee34df1e9 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -137,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 */ diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 0eacdb549..02e7a6e34 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -193,8 +193,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 +208,8 @@ 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")); diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 156bf7439..2cee82734 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -135,7 +135,7 @@ bool IRrecv::decodeLegoPowerFunctions() { 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; } @@ -147,7 +147,7 @@ bool IRrecv::decodeLegoPowerFunctions() { } // Stop bit - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[3 + (2 * LEGO_BITS)], LEGO_BIT_MARK)) { + if (!matchMark(irparams.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; diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 6302b424b..4c5c83841 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -250,14 +250,14 @@ bool IRrecv::decodeNEC() { } // Check header "mark" this must be done for repeat and data - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], NEC_HEADER_MARK)) { + if (!matchMark(irparams.rawbuf[1], NEC_HEADER_MARK)) { return false; } // Check for repeat - here we have another header space length if (decodedIRData.rawlen == 4) { - if (matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_REPEAT_HEADER_SPACE) - && matchMark(decodedIRData.rawDataPtr->rawbuf[3], NEC_BIT_MARK)) { + if (matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) + && matchMark(irparams.rawbuf[3], NEC_BIT_MARK)) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; decodedIRData.command = lastDecodedCommand; @@ -268,7 +268,7 @@ bool IRrecv::decodeNEC() { } // Check command header space - if (!matchSpace(decodedIRData.rawDataPtr->rawbuf[2], NEC_HEADER_SPACE)) { + if (!matchSpace(irparams.rawbuf[2], NEC_HEADER_SPACE)) { #if defined(LOCAL_DEBUG) Serial.print(F("NEC: ")); Serial.println(F("Header space length is wrong")); diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index e07c0b50a..4ad198500 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -266,7 +266,7 @@ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFreque dumpNumberHex(aSerial, (decodedIRData.rawlen + 1) / 2); dumpNumberHex(aSerial, 0); // no repeat data uint16_t timebase = toTimebase(aFrequencyHertz); - compensateAndDumpSequence(aSerial, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space + compensateAndDumpSequence(aSerial, &irparams.rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space aSerial->println(F("\";")); } @@ -335,7 +335,7 @@ size_t IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) { size += dumpNumberHex(aString, toFrequencyCode(frequency)); size += dumpNumberHex(aString, (decodedIRData.rawlen + 1) / 2); size += dumpNumberHex(aString, 0); - size += compensateAndDumpSequence(aString, &decodedIRData.rawDataPtr->rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space + size += compensateAndDumpSequence(aString, &irparams.rawbuf[1], decodedIRData.rawlen - 1, timebase); // skip leading space return size; } diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index d97f11b40..3a826f7c9 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -461,8 +461,8 @@ bool IRrecv::decodeRC6() { } // Check header "mark" and "space", this must be done for repeat and data - if (!matchMark(decodedIRData.rawDataPtr->rawbuf[1], RC6_HEADER_MARK) - || !matchSpace(decodedIRData.rawDataPtr->rawbuf[2], RC6_HEADER_SPACE)) { + if (!matchMark(irparams.rawbuf[1], RC6_HEADER_MARK) + || !matchSpace(irparams.rawbuf[2], RC6_HEADER_SPACE)) { // no debug output, since this check is mainly to determine the received protocol IR_DEBUG_PRINT(F("RC6: ")); IR_DEBUG_PRINTLN(F("Header mark or space length is wrong")); diff --git a/src/ir_Template.hpp b/src/ir_Template.hpp index ce1dab069..f4726da42 100644 --- a/src/ir_Template.hpp +++ b/src/ir_Template.hpp @@ -143,7 +143,7 @@ bool IRrecv::decodeShuzu() { * Next try the decode */ // Check we have the right amount of data (28). The +4 is for initial gap, start bit mark and space + stop bit mark - if (decodedIRData.rawDataPtr->rawlen != (2 * SHUZU_BITS) + 4) { + if (irparams.rawlen != (2 * SHUZU_BITS) + 4) { // no debug output, since this check is mainly to determine the received protocol return false; } From ee8bc421017db7541b29f600c1c5d734cc6be31c Mon Sep 17 00:00:00 2001 From: ArminJo Date: Tue, 29 Jul 2025 15:25:45 +0200 Subject: [PATCH 091/133] Experimental threshold decoder to be activated by USE_THRESHOLD_DECODING --- src/IRProtocol.h | 13 +++-- src/IRProtocol.hpp | 52 +++++++++++++++++- src/IRReceive.hpp | 118 +++++++++++++++++++++++++++++++++++------ src/IRremoteInt.h | 3 ++ src/TinyIR.h | 12 +++-- src/TinyIRReceiver.hpp | 22 +++++--- 6 files changed, 187 insertions(+), 33 deletions(-) diff --git a/src/IRProtocol.h b/src/IRProtocol.h index f7d4cd6dd..4331b0d6f 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -144,9 +144,11 @@ struct PulseDistanceWidthProtocolConstants { /* * 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_WIDTH 0x10 +#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 /* * Carrier frequencies for various protocols @@ -170,8 +172,9 @@ const __FlashStringHelper* getProtocolString(decode_type_t aProtocol); const char* getProtocolString(decode_type_t aProtocol); #endif 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); // A static function to be able to print send or copied received data. - +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); /* * Convenience functions to convert MSB to LSB values */ diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 68ee1130f..477c01a26 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -167,11 +167,61 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap // DEPRECATED (void) aPrintRepeatGap; - printIRResultShort(aSerial, aIRDataPtr); + printIRDataShort(aSerial, aIRDataPtr); } + /* * 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 + */ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) { aSerial->println(F("Overflow")); diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 78d184fb2..da36756ab 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -733,6 +733,7 @@ bool IRrecv::decode() { **********************************************************************************************************************/ /** * Decode pulse distance width protocols. We only check the mark or space length of a 1, otherwise we always assume a 0! + * Timing check of +/- 25 percent by matchSpace() or matchMark(). * * 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. @@ -757,15 +758,13 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; + // Assume PULSE_DISTANCE if aOneMarkMicros == aZeroMarkMicros 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 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) { @@ -774,7 +773,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy * !!!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 :-) + unsigned int 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 { @@ -782,7 +781,7 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy * PULSE_WIDTH here. * !!!We only check variable length mark indicating a 1 or 0!!! */ - tMarkTicks = *tRawBufPointer++; + unsigned int tMarkTicks = *tRawBufPointer++; tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 tRawBufPointer++; } @@ -809,6 +808,81 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy return true; } +/** + * 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! + * + * 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 using the PULSE_DISTANCE decoding. + * + * Input is IrReceiver.irparams.rawbuf[] + * Output is IrReceiver.decodedIRData.decodedRawData + * + * @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 0 or 1 + * @param aIsPulseDistanceProtocol + * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first. + * @return true assume always successful decoding + */ +/* + * Experimental threshold decoder to be activated by USE_THRESHOLD_DECODING + * I hope that this will give better results for noisy signals and protocols with short pulses/ pauses + * Currently experimental and requires up to 310 bytes more program space, if more than 1 protocol is involved + * but saves 90 bytes if only e.g. NEC is selected. + */ +//#define USE_THRESHOLD_DECODING +bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneThresholdMicros, + bool aIsPulseDistanceProtocol, bool aMSBfirst) { + + auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; + + IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop + IRRawDataType tMask = 1UL; // Mask is only used for LSB first + + for (uint_fast8_t i = aNumberOfBits; i > 0; i--) { + + uint16_t tOneThresholdMicros; + if (aIsPulseDistanceProtocol) { + /* + * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here. + * !!!We only check variable length space indicating a 1 or 0!!! + */ + tRawBufPointer++; + tOneThresholdMicros = aOneThresholdMicros - MARK_EXCESS_MICROS; + } else { + tOneThresholdMicros = aOneThresholdMicros + MARK_EXCESS_MICROS; + } + unsigned int tCurrentTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) + bool tBitValue = ((tCurrentTicks * MICROS_PER_TICK) > tOneThresholdMicros); // Check for variable length space indicating a 1 or 0 + + if (!aIsPulseDistanceProtocol) { + tRawBufPointer++; + } + + if (aMSBfirst) { + tDecodedData <<= 1; + } + + if (tBitValue) { + // It's a 1 -> set the bit + if (aMSBfirst) { + tDecodedData |= 1; + } else { + tDecodedData |= tMask; + } + IR_TRACE_PRINTLN(F("=> 1")); + } else { + // do not set the bit + IR_TRACE_PRINTLN(F("=> 0")); + } + tMask <<= 1; + } + decodedIRData.decodedRawData = tDecodedData; + return true; +} + /* * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter */ @@ -823,25 +897,21 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy IRRawDataType tMask = 1UL; // Mask is only used for LSB first 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) { /* * Pulse distance here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration. */ - (void) aZeroSpaceMicros; tRawBufPointer++; - tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) + unsigned int 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. */ - tMarkTicks = *tRawBufPointer++; + unsigned int tMarkTicks = *tRawBufPointer++; tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 tRawBufPointer++; } @@ -1005,10 +1075,28 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa */ bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) { - +#if defined(USE_THRESHOLD_DECODING) + /* + * I hope that this will give better results for noisy signals and protocols with short pulses/ pauses + * Still experimental and requires up to 310 bytes more program space, if more than 1 protocol is involved + * but saves 90 bytes if only e.g. NEC is selected. + */ + bool tIsPulseDistanceProtocol = aProtocolConstants->Flags & PROTOCOL_IS_PULSE_DISTANCE; + uint16_t tOneThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros; + if (tIsPulseDistanceProtocol) { + tOneThresholdMicros = (aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros + + aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros) / 2; + } else { + tOneThresholdMicros = (aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros + + aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros) / 2; + } + return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, tOneThresholdMicros, tIsPulseDistanceProtocol, + (aProtocolConstants->Flags & PROTOCOL_IS_MSB_FIRST)); +#else return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, - aProtocolConstants->Flags); + (aProtocolConstants->Flags & PROTOCOL_IS_MSB_FIRST)); +#endif } bool IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, @@ -1509,14 +1597,14 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) #endif /* - * Print raw data + * 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); + PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); #endif /* * Print number of bits processed diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 0aeb6d331..c373eb81d 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -300,6 +300,9 @@ class IRrecv { bool 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 aOneThresholdMicros, + bool aIsPulseDistanceProtocol, bool aMSBfirst); + bool 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."))); diff --git a/src/TinyIR.h b/src/TinyIR.h index 8e29871e3..ea1ce7bf5 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -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 diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index af66d3c84..7b61f205f 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -184,7 +184,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; @@ -202,9 +202,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; } @@ -229,7 +229,7 @@ void IRPinChangeInterruptHandler(void) { if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_SPACE) && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_SPACE)) { /* - * We had 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) @@ -239,8 +239,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) { @@ -257,13 +258,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; @@ -288,7 +293,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) { /* From 8d2f3024ec6faa9ec9c7c4ce2783a88b34ba0160 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 31 Jul 2025 02:21:16 +0200 Subject: [PATCH 092/133] Threshold decoding added, new handling of MARK_EXCESS_MICROS without strange rounding inconsistency. --- .github/workflows/LibraryBuild.yml | 1 + README.md | 23 +- changelog.md | 9 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 33 +- .../MultipleReceivers/MultipleReceivers.ino | 9 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 11 +- examples/ReceiveDump/ReceiveDump.ino | 6 + examples/SendAndReceive/SendAndReceive.ino | 5 + examples/SimpleReceiver/SimpleReceiver.ino | 1 + examples/UnitTest/UnitTest.ino | 94 +- examples/UnitTest/UnitTest.log | 1998 +++++++---------- keywords.txt | 1 - src/IRProtocol.h | 101 +- src/IRProtocol.hpp | 167 -- src/IRReceive.hpp | 597 +++-- src/IRSend.hpp | 482 ++-- src/IRremote.hpp | 64 +- src/IRremoteInt.h | 59 +- src/ir_BoseWave.hpp | 10 +- src/ir_Denon.hpp | 72 +- src/ir_DistanceWidthProtocol.hpp | 124 +- src/ir_FAST.hpp | 16 +- src/ir_JVC.hpp | 15 +- src/ir_Kaseikyo.hpp | 20 +- src/ir_LG.hpp | 21 +- src/ir_Lego.hpp | 105 +- src/ir_MagiQuest.hpp | 46 +- src/ir_NEC.hpp | 26 +- src/ir_Others.hpp | 10 +- src/ir_Samsung.hpp | 27 +- src/ir_Sony.hpp | 10 +- 32 files changed, 2020 insertions(+), 2145 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index ec5dccc66..e819d7e3d 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -91,6 +91,7 @@ jobs: - arduino-boards-fqbn: arduino:avr:uno|DEBUG_TRACE build-properties: # the flags were put in compiler.cpp.extra_flags + UnitTest: -DUSE_THRESHOLD_DECODER IRremoteExtensionTest: -DIR_SEND_PIN=3 TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER All: -DEBUG -DTRACE diff --git a/README.md b/README.md index 1c16c6615..99c4ce465 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A library enabling the sending & receiving of infra-red signals.     [![Badge Version](https://img.shields.io/github/v/release/Arduino-IRremote/Arduino-IRremote?include_prereleases&style=for-the-badge&color=33660e&labelColor=428813&logoColor=white&logo=DocuSign)](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest)     -[![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master) +[![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremoteMultipleMultiple/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)     [![Badge LibraryBuild](https://img.shields.io/github/actions/workflow/status/Arduino-IRremote/Arduino-IRremote/LibraryBuild.yml?branch=master&style=for-the-badge&color=551f47&labelColor=752a61)](https://github.com/Arduino-IRremote/Arduino-IRremote/actions)
@@ -67,7 +67,8 @@ 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 and sender instances](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receiver-and-sender-instances) + * [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) @@ -727,15 +728,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 instances -**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 Ω**.
@@ -889,8 +895,9 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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. | | `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. | diff --git a/changelog.md b/changelog.md index 0ffd0ffcf..4e985c7fe 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,14 @@ # Changelog The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master -# 4.4.4 +# 4.5.0 +- 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. +- Added support for multiple receiver instances. +- Minor bug fixes for DEBUG. # 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. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 48b5f16ed..668922eb8 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -59,6 +59,7 @@ #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 135. @@ -124,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) @@ -184,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) @@ -368,17 +374,14 @@ void printIRResultOnLCD() { 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; @@ -386,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) { @@ -473,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/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index b35ca00e6..254db7e1e 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -32,6 +32,8 @@ #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. @@ -58,8 +60,7 @@ //#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 -#define IR_RECEIVE_PIN_OF_SECOND_RECEIVER 5 -void UserIRReceiveTimerInterruptHandler(); // must be before line #include +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 @@ -69,7 +70,7 @@ void UserIRReceiveTimerInterruptHandler(); // must be before line #include irparams.IRReceivePin); diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 45dc008be..f156aa6f6 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -249,7 +249,7 @@ void sendCode(storedIRDataStruct *aIRDataToSend) { * Use the write function, which does the switch for different protocols */ IrSender.write(&aIRDataToSend->receivedIRData); - printIRResultShort(&Serial, &aIRDataToSend->receivedIRData); + printIRDataShort(&Serial, &aIRDataToSend->receivedIRData); } } diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index b4c3edd10..4b44fc3d8 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -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,6 +60,7 @@ //#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 :-( !!! @@ -95,7 +95,9 @@ //#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 135. // 20 is taken as default if not otherwise specified / defined. @@ -176,8 +178,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 // FLASHEND >= 0x3FFF } @@ -228,7 +235,7 @@ void loop() { #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")); diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index d1921efb4..7868f38c3 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -90,8 +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(); diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 9b80ab7ed..441277a9c 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -89,8 +89,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/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 95eaee8c7..84b040376 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -62,6 +62,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. +//#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. /* diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index a99b84b1b..e03e4d1f9 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -46,6 +46,7 @@ //#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 458 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. @@ -86,6 +87,10 @@ #define DECODE_SONY #define DECODE_SAMSUNG #define DECODE_LG +# if defined(USE_THRESHOLD_DECODER) +#define DECODE_LEGO_PF // LEGO is skipped, since it is difficult to receive because of its short marks and spaces +# endif +#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!!! @@ -100,10 +105,10 @@ #define DECODE_FAST //#define DECODE_WHYNTER -//#define DECODE_LEGO_PF -#endif //#undef IR_SEND_PIN // enable this, if you need to set send pin programmatically using uint8_t tSendPin below + +#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints errors which prevents data to be decoded as distance width data #include #if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN) @@ -117,8 +122,8 @@ # 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 @@ -220,8 +225,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); @@ -247,10 +257,11 @@ void checkReceivedRawData(IRRawDataType aRawData) { || digitalRead(DEBUG_BUTTON_PIN) == LOW # endif ) { - // We have an unknown protocol, print more info + // 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")); @@ -266,6 +277,7 @@ void checkReceivedRawData(IRRawDataType aRawData) { PrintULL::print(&Serial, aRawData, HEX); #endif Serial.println(); + IrReceiver.printIRResultAsCArray(&Serial, false, false); } } IrReceiver.resume(); @@ -296,7 +308,7 @@ void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize) || digitalRead(DEBUG_BUTTON_PIN) == LOW # endif ) { - // We have an unknown protocol, print more info + // We have an unknown protocol or debug button is held low, print more info IrReceiver.printIRResultRawFormatted(&Serial, true); } #endif @@ -312,6 +324,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++; } @@ -421,9 +434,16 @@ void loop() { Serial.print(sAddress, HEX); Serial.print(F(" command=0x")); Serial.print(sCommand, HEX); + if(sRepeats > 0) { + Serial.print(F(" ")); + Serial.print(sRepeats, HEX); + Serial.print(F(" repeats")); + } + Serial.println(); Serial.println(); +#if defined(DECODE_NEC) 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")); @@ -437,12 +457,12 @@ void loop() { * Complete NEC frames as repeats to force decoding as NEC2 are tested here */ for (int8_t i = 0; i < sRepeats; i++) { -#if defined(DEBUG_BUTTON_PIN) +# if defined(DEBUG_BUTTON_PIN) if (digitalRead(DEBUG_BUTTON_PIN) != LOW) { // If debug is enabled, printing time (50 ms) is sufficient as delay delayMicroseconds(NEC_REPEAT_DISTANCE - 20000); // 20000 is just a guess } -#endif +# endif IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); } @@ -460,6 +480,7 @@ void loop() { IrSender.sendNEC2(sAddress, sCommand, 0); 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. @@ -467,6 +488,7 @@ void loop() { # 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. IRRawDataType tRawData[4]; +# if defined(DECODE_NEC) /* * Send constant values only once in this demo */ @@ -516,6 +538,7 @@ void loop() { IrSender.sendNECMSB(0x40802CD3, 32, false); checkReceive(0x0102, 0x34); delay(DELAY_AFTER_SEND); +# endif // defined(DECODE_NEC) # if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432")); @@ -629,7 +652,8 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600")); + Serial.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]; @@ -649,14 +673,16 @@ void loop() { checkReceivedRawData(sCommand); 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); checkReceive(sAddress & 0x1F, sCommand & 0x7F); delay(DELAY_AFTER_SEND); +# endif - Serial.println(F("Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300")); + 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); @@ -696,6 +722,7 @@ void loop() { } #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); @@ -707,6 +734,7 @@ void loop() { IrSender.sendApple(sAddress & 0xFF, sCommand, 0); checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); +#endif #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic")); @@ -729,15 +757,15 @@ void loop() { #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 @@ -812,8 +840,26 @@ void loop() { 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); # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) @@ -846,14 +892,6 @@ void loop() { 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 */ @@ -910,14 +948,6 @@ void loop() { delay(DELAY_AFTER_SEND); #endif - /* - * LEGO is skipped, since it is difficult to receive because of its short marks and spaces - */ -// Serial.println(F("Send Lego with 2 channel and with 4 command bits")); -// Serial.flush(); -// IrSender.sendLegoPowerFunctions(sAddress, sCommand, LEGO_MODE_COMBO, true); -// checkReceive(sAddress, sCommand); // never has success for Lego protocol :-( -// delay(DELAY_AFTER_SEND); /* * Force buffer overflow */ diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 6e5a43fe3..df0e73796 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -1,46 +1,46 @@ -START ../src/UnitTest.cpp from Jul 15 2025 +START ../src/UnitTest.cpp from Jul 31 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 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, Lego Power Functions, Bosewave, MagiQuest, Universal Pulse Distance Width, Hash at pin 2 Use ReceiveCompleteCallback Receive buffer length is 400 Send IR signals at pin 3 If you connect debug pin 5 to ground, raw data is always printed Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us 16000 us is the (minimum) gap, after which the start of a new IR packet is assumed -20 us are subtracted from all marks and added to all spaces for decoding +Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0 address=0xFFF1 command=0x76 Send NEC with 8 bit address -Protocol=NEC Address=0xF1 Command=0x76 Raw-Data=0x89760EF1 32 bits LSB first Gap=1049200us Duration=67800us +Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=753700us, Duration=67800us Send with: IrSender.sendNEC(0xF1, 0x76, ); rawData[68]: - -1049200 - +8950,-4400 - + 600,-1600 + 650,- 500 + 600,- 500 + 600,- 550 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 550 + 600,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + -753700 + +8950,-4350 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 600,- 550 + 600,-1600 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 600,- 550 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650 + + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 + + 600 Duration=67800us Send NEC with 16 bit address -Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1061800us Duration=73350us +Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764300us, Duration=73350us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); rawData[68]: - -1061800 + -764300 +8950,-4400 - + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,-1650 + 600,-1600 + 600,-1650 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650 @@ -48,156 +48,156 @@ Duration=73350us Send NEC2 with 16 bit address -Protocol=NEC Address=0xFFF1 Command=0x76 Raw-Data=0x8976FFF1 32 bits LSB first Gap=1062300us Duration=73400us +Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764750us, Duration=73350us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); rawData[68]: - -1062300 + -764750 +8950,-4400 - + 650,-1600 + 650,- 500 + 600,- 550 + 600,- 500 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 600,-1650 - + 600,- 500 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,-1600 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550 + + 600,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650 -Duration=73400us +Duration=73350us 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 Gap=1071050us Duration=67900us +Protocol=NEC Address=0x80, Command=0x45, Raw-Data=0xBA457F80, 32 bits, LSB first, Gap=773500us, Duration=67800us Send with: IrSender.sendNEC(0x80, 0x45, ); rawData[68]: - -1071050 + -773500 +9100,-4350 - + 650,- 500 + 650,- 500 + 650,- 600 + 550,- 550 + + 650,- 450 + 650,- 500 + 650,- 550 + 600,- 550 + 650,- 500 + 650,- 500 + 650,- 500 + 650,-1600 + 650,-1550 + 650,-1550 + 650,-1600 + 600,-1550 - + 700,-1500 + 650,-1600 + 650,-1550 + 650,- 500 + + 650,-1550 + 650,-1600 + 600,-1600 + 650,- 450 + 650,-1550 + 650,- 500 + 650,-1600 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 450 - + 700,- 450 + 700,-1500 + 650,- 500 + 650,-1600 - + 650,-1550 + 650,-1550 + 650,- 500 + 650,-1550 + + 600,- 500 + 700,- 450 + 650,-1600 + 600,- 550 + + 650,- 450 + 750,-1450 + 650,- 500 + 650,-1600 + + 600,-1600 + 600,-1600 + 650,- 500 + 650,-1550 + 650 -Duration=67900us +Duration=67800us 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 Gap=1068200us Duration=68000us +Protocol=NEC Address=0x4, Command=0x8, Raw-Data=0xF708FB04, 32 bits, LSB first, Gap=770700us, Duration=68050us Send with: IrSender.sendNEC(0x4, 0x8, ); rawData[68]: - -1068200 + -770700 +8950,-4400 - + 650,- 500 + 650,- 450 + 650,-1600 + 650,- 500 - + 600,- 550 + 600,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 650,-1600 + 650,- 500 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 550 + 550,- 550 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + + 650,- 500 + 650,- 500 + 600,-1650 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,- 500 + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650 -Duration=68000us + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600 +Duration=68050us 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=1066450us Duration=55550us +Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=768950us, Duration=55600us Send with: IrSender.sendOnkyo(0x102, 0x304, ); rawData[68]: - -1066450 - +8950,-4350 - + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,- 500 + 650,- 550 + 600,- 500 + -768950 + +8950,-4400 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,- 500 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1600 + 650,- 500 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500 + 600 -Duration=55550us +Duration=55600us 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=1068300us Duration=61150us +Protocol=NEC Address=0x102, Command=0x34, Raw-Data=0xCB340102, 32 bits, LSB first, Gap=770950us, Duration=61100us Send with: IrSender.sendNEC(0x102, 0x34, ); rawData[68]: - -1068300 - +8950,-4400 - + 650,- 450 + 650,-1600 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + -770950 + +8900,-4400 + + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + 650,-1600 - + 650,- 450 + 650,- 500 + 650,-1600 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600 + 600 -Duration=61150us +Duration=61100us 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=1067800us Duration=54200us +Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=770400us, Duration=54150us Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1067800 - +3500,-1650 - + 500,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 400 + 450,- 400 + -770400 + +3450,-1700 + + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 - + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 450 - + 450,- 400 + 500,- 350 + 450,- 450 + 450,- 400 - + 500,-1250 + 450,- 400 + 450,- 400 + 500,- 400 - + 450,- 400 + 500,- 350 + 450,- 450 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,-1250 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 + + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 400 + + 500,- 400 + 500,- 350 + 450,- 450 + 450,- 400 + + 500,-1200 + 450,- 450 + 450,- 400 + 500,- 350 + + 500,- 350 + 500,- 400 + 450,- 400 + 450,- 450 + + 450,- 400 + 450,-1250 + 450,- 450 + 500,-1200 + 450 -Duration=54200us +Duration=54150us Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400 -LSB first -Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Gap=1084800us Duration=53200us +Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=787100us, Duration=53200us Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1084800 - +3450,-1650 - + 500,- 350 + 500,-1150 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 + -787100 + +3500,-1650 + + 450,- 400 + 450,-1200 + 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,- 400 - + 450,-1200 + 500,-1200 + 500,- 350 + 500,-1200 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 400 + + 450,- 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 - + 500,- 350 + 500,- 400 + 450,- 350 + 500,- 350 - + 500,-1200 + 500,- 400 + 450,- 350 + 500,- 350 - + 500,- 400 + 450,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1250 - + 450 + + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 + + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1200 + + 500 Duration=53200us -MSB first -Protocol=Panasonic Address=0xB Command=0x10 Raw-Data=0xA01000B0 48 bits LSB first Gap=1077450us Duration=53200us +Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=779800us, Duration=53200us Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawData[100]: - -1077450 - +3500,-1650 - + 500,- 350 + 500,-1200 + 500,- 300 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 - + 500,- 350 + 500,- 400 + 450,- 350 + 500,- 350 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,- 400 - + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + -779800 + +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 + 550,- 300 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,-1200 + 500,- 300 + 500,- 350 + 500,- 350 + + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 400 + + 450,- 400 + 450,- 400 + 450,- 400 + 450,- 400 + + 450,-1200 + 500,- 350 + 500,- 350 + 550,- 300 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1200 + 500 @@ -205,402 +205,402 @@ Duration=53200us 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=1084300us Duration=138250us +Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=786600us, Duration=138350us 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, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4350, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); rawData[148]: - -1084300 - +8850,-4400 - + 600,-1600 + 650,- 500 + 600,- 550 + 600,- 550 + -786600 + +8900,-4350 + + 600,-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,- 600 - + 550,- 550 + 600,-1650 + 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,-1700 - + 600,-1600 + 600,- 550 + 600,- 550 + 600,-1650 + + 550,-1650 + 600,- 550 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1600 + + 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,-1600 + 600,-1650 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,-1600 - + 600,- 550 + 650,-1600 + 600,- 550 + 600,-1650 + + 550,- 600 + 550,-1650 + 600,-1650 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1700 + + 550,- 600 + 550,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1650 + 600,- 550 + 600,-1650 + 600,- 550 + 600 -Duration=138250us +Duration=138350us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300 -Protocol=PulseDistance Raw-Data=0xDCBA9 52 bits LSB first Gap=1121150us Duration=48300us +Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822500us, Duration=48200us Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 400, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); rawData[108]: - -1121150 - + 400,- 550 - + 350,- 550 + 650,- 250 + 650,- 250 + 600,- 300 - + 650,- 250 + 350,- 550 + 650,- 250 + 650,- 250 - + 350,- 550 + 400,- 500 + 650,- 250 + 650,- 250 + -822500 + + 350,- 550 + + 350,- 550 + 650,- 250 + 700,- 200 + 650,- 250 + + 700,- 200 + 400,- 550 + 600,- 250 + 650,- 250 + + 400,- 550 + 350,- 550 + 600,- 250 + 650,- 250 + 650,- 250 + 700,- 200 + 400,- 500 + 650,- 250 - + 400,- 550 + 650,- 200 + 400,- 550 + 650,- 200 - + 700,- 250 + 350,- 550 + 350,- 550 + 650,- 250 - + 350,- 550 + 350,- 550 + 350,- 550 + 650,- 250 - + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 550 - + 400,- 550 + 650,- 250 + 650,- 250 + 350,- 550 - + 650,- 250 + 350,- 550 + 650,- 250 + 350,- 550 - + 350,- 550 + 350,- 550 + 650,- 250 + 400,- 500 - + 700,- 200 + 650,- 250 + 400,- 550 + 350,- 550 - + 400,- 500 + 650,- 250 + 400,- 500 + 400,- 550 + + 400,- 550 + 600,- 250 + 350,- 600 + 600,- 300 + + 600,- 300 + 350,- 550 + 300,- 600 + 600,- 300 + + 350,- 550 + 300,- 600 + 350,- 550 + 600,- 300 + + 600,- 300 + 600,- 300 + 600,- 250 + 400,- 550 + + 350,- 550 + 650,- 250 + 650,- 250 + 400,- 500 + + 650,- 250 + 350,- 600 + 600,- 300 + 350,- 550 + + 350,- 550 + 350,- 600 + 600,- 250 + 350,- 600 + + 600,- 300 + 600,- 300 + 300,- 600 + 300,- 550 + + 400,- 550 + 600,- 300 + 350,- 550 + 350,- 550 + 350 -Duration=48300us +Duration=48200us 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=1100850us Duration=48500us +Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=802750us, Duration=48450us Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); rawData[108]: - -1100850 + -802750 + 350,- 600 - + 350,- 550 + 650,- 250 + 650,- 250 + 650,- 250 - + 650,- 200 + 400,- 550 + 650,- 200 + 650,- 250 - + 400,- 500 + 400,- 550 + 650,- 250 + 650,- 200 - + 650,- 250 + 700,- 200 + 400,- 500 + 700,- 200 - + 400,- 550 + 650,- 250 + 350,- 550 + 650,- 250 - + 650,- 250 + 350,- 550 + 400,- 500 + 650,- 250 - + 400,- 500 + 400,- 550 + 350,- 550 + 650,- 250 - + 650,- 250 + 650,- 200 + 650,- 300 + 350,- 550 + + 350,- 550 + 600,- 300 + 600,- 300 + 600,- 300 + + 600,- 300 + 350,- 550 + 600,- 300 + 600,- 300 + + 350,- 550 + 350,- 550 + 600,- 300 + 600,- 300 + + 600,- 300 + 600,- 300 + 350,- 550 + 600,- 300 + + 350,- 550 + 600,- 300 + 300,- 600 + 600,- 300 + + 600,- 300 + 350,- 550 + 350,- 550 + 650,- 250 + + 350,- 600 + 350,- 550 + 350,- 550 + 600,- 300 + + 600,- 300 + 600,- 300 + 600,- 300 + 350,- 550 + 350,- 550 + 650,- 250 + 650,- 250 + 400,- 500 - + 700,- 250 + 350,- 550 + 650,- 250 + 350,- 550 - + 350,- 550 + 350,- 550 + 650,- 250 + 350,- 550 - + 650,- 250 + 650,- 250 + 350,- 550 + 350,- 550 - + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 550 - + 650 -Duration=48500us + + 650,- 250 + 350,- 550 + 650,- 300 + 300,- 550 + + 350,- 600 + 350,- 550 + 600,- 250 + 350,- 600 + + 600,- 300 + 600,- 250 + 350,- 550 + 400,- 550 + + 300,- 600 + 600,- 300 + 350,- 550 + 350,- 550 + + 600 +Duration=48450us 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=1098850us Duration=20950us +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]: - -1098850 + -800750 +6000,- 450 - +1550,- 400 + 550,-1450 + 550,-1450 +1550,- 450 + +1550,- 450 + 500,-1450 + 550,-1450 +1550,- 450 + 550,-1450 + 550,-1450 + 550,-1450 + 550 Duration=20950us 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=1041700us Duration=21000us +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]: - -1041700 - +2450,- 550 - + 650,- 550 +1250,- 500 +1250,- 550 + 650,- 550 + -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 -Duration=21000us +Duration=21050us Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 -Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first Gap=1041200us Duration=24600us -Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1100, 450, 650, 250, 350, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); +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]: - -1041200 - +1100,- 450 - + 650,- 250 + 400,- 200 + 400,- 200 + 400,- 250 - + 350,- 250 + 650,- 250 + 350,- 250 + 400,- 200 - + 700,- 200 + 700,- 250 + 350,- 250 + 350,- 250 - + 350,- 250 + 400,- 200 + 700,- 200 + 400,- 250 - + 650,- 250 + 350,- 250 + 650,- 250 + 400,- 200 - + 400,- 250 + 650,- 250 + 650,- 250 + 350,- 250 - + 650,- 250 + 650,- 250 + 650,- 250 + 350,- 250 - + 350,- 250 + 350,- 250 + 350,- 250 + 650 -Duration=24600us + -744500 + +1050,- 500 + + 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 + + 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 1=576|576, 0=287|864 -Protocol=MagiQuest Address=0xFF00 Command=0x176 Raw-Data=0x6BCDFF00 56 bits MSB first Gap=1070650us Duration=63950us +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]: - -1070650 + -773750 + + 350,- 850 + 300,- 850 + 300,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 850 + 300,- 800 - + 650,- 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 + 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 - + 350,- 850 + 350,- 800 + 300,- 800 + 350,- 800 + + 300,- 900 + 300,- 850 + 300,- 800 + 350,- 800 + + 350,- 800 + 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 - + 350,- 800 + 650,- 500 + 650,- 550 + 600,- 550 - + 300,- 800 + 650,- 550 + 600,- 550 + 300,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 650,- 500 - + 650,- 500 + 350,- 800 + 350,- 800 + 650 -Duration=63950us + + 600,- 550 + 350,- 800 + 350,- 800 + 600 +Duration=63850us Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xFFF1 Command=0x7776 Raw-Data=0x7776FFF1 32 bits LSB first Gap=1087450us Duration=76750us +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]: - -1087450 + -790650 +8950,-4400 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 + + 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 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 - + 650 -Duration=76750us + + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550 + + 600 +Duration=76650us Send Apple -Protocol=Apple Address=0xF1 Command=0x76 Raw-Data=0xF17687EE 32 bits LSB first Gap=1061400us Duration=72250us +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]: - -1061400 + -763800 +8950,-4400 - + 650,- 500 + 600,-1650 + 600,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1650 - + 600,-1600 + 600,-1600 + 650,-1600 + 650,- 500 + + 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,-1600 + 650,-1600 + 650,-1600 + 650,- 450 - + 650,-1600 + 650,- 450 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650 + + 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 Duration=72250us Send Panasonic -Protocol=Panasonic Address=0xFF1 Command=0x76 Raw-Data=0x9976FF10 48 bits LSB first Gap=1061100us Duration=64450us +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]: - -1061100 + -763550 +3450,-1700 - + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 450,-1250 + 500,- 400 + 500,- 350 + 500,- 400 - + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1200 - + 500,-1250 + 500,-1200 + 500,-1250 + 450,-1300 - + 450,- 400 + 450,-1250 + 450,-1300 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,-1250 + 500,- 400 - + 450,-1250 + 500,- 350 + 500,- 400 + 500,-1200 + + 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 - + 500 -Duration=64450us + + 450,-1300 + 450,- 400 + 500,- 350 + 500,-1250 + + 450 +Duration=64400us Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xFF1 Command=0x76 Extra=0x4711 Raw-Data=0x9A76FF13 48 bits LSB first Gap=1081300us Duration=69550us +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]: - -1081300 + -783450 +3500,-1650 + 500,-1250 + 450,- 400 + 500,- 350 + 500,- 400 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 500,-1200 + 500,-1250 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,-1250 + 500,- 350 - + 500,-1250 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,-1250 + 450,- 400 + 500,- 350 + 450,- 450 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 - + 500,- 350 + 500,-1250 + 450,-1250 + 500,- 350 - + 500,-1250 + 500,-1200 + 500,-1250 + 500,- 350 - + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 - + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 + + 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 + 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 Gap=1082100us Duration=67850us +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]: - -1082100 - +3450,-1700 - + 500,- 350 + 500,- 350 + 500,-1250 + 500,- 350 - + 500,-1250 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 - + 500,- 400 + 500,-1200 + 500,-1250 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,- 400 + 450,- 400 + 500,-1250 - + 450,-1250 + 500,- 400 + 500,- 350 + 500,-1250 - + 450 + -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 + + 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 Duration=67850us -Send Denon -Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0xED1 15 bits LSB first Gap=1079850us Duration=23150us +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]: - -1079850 - + 300,-1750 + 300,- 750 + 300,- 750 + 300,- 750 - + 300,-1750 + 350,- 700 + 350,-1700 + 350,-1750 - + 300,- 750 + 300,-1750 + 350,-1750 + 250,-1800 - + 350,- 700 + 350,- 700 + 300,- 750 + 300 -Duration=23150us + -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 +Duration=23100us -Send Denon/Sharp variant -Protocol=Denon Address=0x11 Command=0x76 Raw-Data=0x2ED1 15 bits LSB first Gap=1022000us Duration=24200us -Send with: IrSender.sendDenon(0x11, 0x76, ); +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]: - -1022000 - + 300,-1750 + 350,- 700 + 350,- 700 + 300,- 750 - + 300,-1750 + 350,- 700 + 350,-1700 + 300,-1800 - + 300,- 750 + 300,-1750 + 350,-1750 + 300,-1750 - + 350,- 700 + 350,-1750 + 300,- 700 + 350 -Duration=24200us + -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,-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 Gap=1024200us Duration=21050us +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]: - -1024200 - +2500,- 500 + -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 + + 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 Gap=1040000us Duration=26400us +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]: - -1040000 - +2400,- 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 -Duration=26400us +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 Gap=1043700us Duration=35450us +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]: - -1043700 - +2450,- 550 - + 700,- 500 +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 + 650,- 550 + 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 -Duration=35450us +Duration=35400us Send Samsung 8 bit command and 8 bit address -Protocol=Samsung Address=0xF1 Command=0x76 Raw-Data=0x8976F1F1 32 bits LSB first Gap=1048550us Duration=65550us +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]: - -1048550 - +4500,-4400 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1650 - + 550,-1650 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + -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=65550us +Duration=65600us Send Samsung 16 bit command and address -Protocol=Samsung Address=0xFFF1 Command=0x9876 Raw-Data=0x9876FFF1 32 bits LSB first Gap=1063650us Duration=68950us +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]: - -1063650 + -766100 +4500,-4400 - + 600,-1650 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 600,-1650 + 650,-1600 + 600,-1600 + 650,-1600 + + 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 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 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 Gap=1063500us Duration=95850us +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]: - -1063500 - +4500,-4400 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + -765950 + +4500,-4450 + + 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,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 + + 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 -Duration=95850us +Duration=95900us Send RC5 -Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first Gap=1080100us Duration=23100us +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]: - -1080100 - + 950,- 800 + -782100 + + 900,- 850 +1850,-1700 +1850,- 850 + 900,- 850 + 950,-1700 - + 950,- 850 + 950,- 800 +1850,-1700 + 950,- 850 - +1800 -Duration=23100us + + 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 Gap=1038950us Duration=23100us +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]: - -1038950 + -742250 +1800,-1700 - + 950,- 850 +1800,- 850 + 950,- 850 + 900,-1750 + + 950,- 850 +1800,- 850 + 950,- 850 + 950,-1700 + 950,- 850 + 900,- 850 +1850,-1700 + 950,- 850 +1800 Duration=23100us Send RC6 -Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first Gap=1036250us Duration=23300us +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]: - -1036250 - +2650,- 850 - + 500,- 850 + 500,- 400 + 500,- 400 + 500,- 850 - +1400,- 400 + 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 @@ -608,191 +608,205 @@ Duration=23300us 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=1046300us Duration=36800us +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]: - -1046300 - +2700,- 850 - + 500,- 350 + 500,- 400 + 500,- 850 +1400,-1300 - + 950,- 800 + 500,- 400 + 950,- 450 + 450,- 400 + -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,- 400 + 500,- 450 - + 450,- 450 + 450,- 450 + 500,- 800 + 500,- 400 - + 500,- 400 +1000,- 800 + 950,- 450 + 450,- 450 - + 450,- 850 + 950,- 400 + 500,- 850 + 500 + + 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 Bang&Olufsen +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]: + -765200 + + 350,- 800 + 350,- 800 + 300,- 850 + 350,- 800 + + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 + + 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 + + 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,- 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 +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]: - -1060200 - + 300,-2800 - + 300,-2850 + 250,-12750 + 250,-2800 + 300,-9000 - + 300,-5950 + 250,-5950 + 250,-5950 + 200,-2900 - + 250,-5950 + 250,-5950 + 250,-9000 + 250,-2900 - + 250,-9050 + 250,-5950 + 250,-5900 + 300,-2850 - + 250,-9000 + 300,-5950 + 250,-2850 + 250,-12100 - + 300 + -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=1060200us Duration=6500us +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=114950us +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,-2800 - + 300,-9000 + 300,-5950 + 250,-5950 + 250,-5950 - + 200,-2900 + 250,-5950 + 250,-5950 + 250,-9000 - + 250,-2900 + 250,-9050 + 250,-5950 + 250,-5900 - + 300,-2850 + 250,-9000 + 300,-5950 + 250,-2850 - + 250,-12100 + 300 -Duration=114950us - - -Send MagiQuest -Protocol=MagiQuest Address=0xFFF1 Command=0x76 Raw-Data=0x6BCDFFF1 56 bits MSB first Gap=1097800us Duration=63950us -Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -1097800 - + 300,- 800 + 350,- 800 + 350,- 800 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 - + 650,- 500 + 650,- 500 + 350,- 800 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 350,- 800 + 350,- 800 + 650,- 500 - + 650,- 500 + 300,- 850 + 650,- 500 + 650,- 500 - + 650,- 550 + 600,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 650,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 650,- 500 + 650,- 500 + 350,- 800 - + 350,- 800 + 350,- 800 + 650,- 550 + 350,- 800 - + 300,- 850 + 600,- 550 + 600,- 550 + 600,- 550 - + 350,- 800 + 600,- 550 + 600,- 550 + 300,- 850 - + 350,- 800 + 350,- 800 + 650,- 500 + 600,- 550 - + 300,- 850 + 650,- 500 + 650,- 500 + 650 -Duration=63950us + + 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 Gap=1088550us Duration=40450us +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]: - -1088550 + -804700 +8400,-4150 - + 550,-1550 + 550,- 500 + 550,- 500 + 600,- 450 + + 600,-1500 + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 + 600,-1500 + 600,-1500 + 600,-1500 - + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 - + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 + + 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 Gap=1042750us Duration=59350us +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]: - -1042750 - +8900,-4150 - + 550,-1500 + 550,-1550 + 550,-1500 + 550,-1550 - + 550,- 500 + 550,- 500 + 550,- 500 + 500,-1550 - + 550,-1550 + 500,- 500 + 600,- 500 + 500,-1550 - + 550,-1550 + 550,- 500 + 550,- 500 + 550,- 500 - + 500,- 500 + 600,-1500 + 550,-1500 + 550,-1550 - + 550,- 450 + 600,-1500 + 550,-1550 + 550,- 500 - + 550,-1500 + 550,-1500 + 550,-1550 + 550,- 500 + -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 -Duration=59350us +Duration=59450us Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Gap=1059500us Duration=26800us +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]: - -1059500 + -762100 +1050,-1450 - + 550,- 400 + 600,-1400 + 550,-1400 + 600,- 450 - + 550,-1400 + 550,-1400 + 600,-1400 + 600,- 400 - + 600,-1350 + 600,- 400 + 600,- 400 + 600,-1400 - + 550,- 400 + 600,- 400 + 600,- 400 + 600,-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 Duration=26800us Send FAST -Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first Gap=1043550us Duration=28950us +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]: - -1043550 - +2150,-1000 - + 600,- 450 + 600,-1500 + 600,-1500 + 600,- 450 - + 600,-1550 + 550,-1500 + 600,-1500 + 600,- 450 - + 600,-1500 + 600,- 450 + 600,- 450 + 600,-1500 - + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 - + 600 -Duration=28950us + -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 450 marks and spaces Overflow Try to increase the "RAW_BUFFER_LENGTH" value of 400 in ../src/UnitTest.cpp rawData[400]: - -1042750 - + 250,- 500 - + 300,- 450 + 300,- 500 + 250,- 450 + 300,- 450 - + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 250,- 500 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 - + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 500 + 200,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + -745700 + + 200,- 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,- 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 + + 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,- 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 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 + + 250,- 500 + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 450 + 250,- 500 + 250,- 500 + 250,- 500 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 250 -Duration=149550us + + 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 +Duration=149500us ERROR: Unknown protocol @@ -802,235 +816,235 @@ 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 Gap=1220500us Duration=67850us +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]: - -1220500 + -923450 +8950,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 550 - + 600,-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 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + + 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 Raw-Data=0x78870DF2 32 bits LSB first Repeat Gap=69150us Duration=67800us +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]: - -69150 - +8950,-4400 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 550 + 600,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550 - + 600,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,- 550 + 600,- 500 + 600,- 500 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 - + 600 + -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 Gap=1062250us Duration=67850us +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]: - -1062250 - +8950,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + -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=67850us +Duration=67800us Send NEC2 with 16 bit address -Protocol=NEC Address=0xF2 Command=0x87 Raw-Data=0x78870DF2 32 bits LSB first Gap=1061850us Duration=67800us +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]: - -1061850 - +8950,-4400 - + 600,- 500 + 650,-1650 + 600,- 500 + 600,- 500 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 600,-1650 + 600,- 500 + 650,-1600 + 650,-1600 + -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 + 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 + + 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 Duration=67800us Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xF2 Command=0x8887 Raw-Data=0x888700F2 32 bits LSB first Gap=1062500us Duration=62200us +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]: - -1062500 - +8900,-4450 - + 600,- 500 + 650,-1600 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + -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,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,- 500 + 650,- 450 + 650,- 500 + 600,-1650 - + 600 -Duration=62200us + + 650 +Duration=62300us Send Apple -Protocol=Apple Address=0xF2 Command=0x87 Raw-Data=0xF28787EE 32 bits LSB first Gap=1060900us Duration=71150us +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]: - -1060900 + -763450 +8950,-4400 - + 600,- 500 + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 550 + 600,-1600 - + 650,- 500 + 600,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650 + + 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 Gap=1061050us Duration=59350us +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]: - -1061050 + -763500 +3500,-1700 + 450,- 400 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 350 + 500,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,- 400 + 450,- 400 + 500,- 400 + 450,- 450 - + 450,-1250 + 500,-1250 + 450,-1250 + 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 - + 450,- 400 + 500,- 350 + 500,- 400 + 500,-1200 - + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 + + 500,- 350 + 450,-1300 + 450,- 400 + 500,-1200 + 500 Duration=59350us Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xF2 Command=0x87 Extra=0x4711 Raw-Data=0xAB870F23 48 bits LSB first Gap=1081050us Duration=66150us +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]: - -1081050 - +3450,-1700 - + 500,-1250 + 450,- 400 + 450,- 400 + 500,- 400 - + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 350 + -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,- 350 + 500,- 400 + 450,-1250 + 500,- 350 - + 500,-1250 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,-1250 + 500,-1200 + 500,-1250 + 500,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,-1250 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1200 - + 500,- 400 + 450,-1250 + 500,- 400 + 450,-1250 - + 500 + + 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 Duration=66150us Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0xF2 Command=0x87 Raw-Data=0xA8870F20 48 bits LSB first Gap=1081850us Duration=62700us +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]: - -1081850 + -784050 +3450,-1700 - + 450,- 400 + 500,- 350 + 500,-1250 + 500,- 350 - + 500,-1250 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,- 400 + 450,-1250 + 500,- 350 + 500,- 400 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 450,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,-1250 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400 - + 450,-1250 + 500,-1250 + 450,-1250 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,- 350 + 500,-1250 - + 450,- 400 + 500,- 400 + 450,- 400 + 500,-1250 - + 450,- 400 + 500,-1200 + 500,- 400 + 450,-1250 - + 500 + + 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,- 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 Duration=62700us -Send Denon -Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x10F2 15 bits LSB first Gap=1079550us Duration=22150us +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]: - -1079550 - + 350,- 700 + 300,-1750 + 350,- 700 + 350,- 700 - + 350,-1700 + 350,-1750 + 300,-1750 + 350,-1750 - + 300,- 700 + 350,- 700 + 300,- 750 + 350,- 700 - + 300,-1750 + 350,- 700 + 350,- 700 + 350 -Duration=22150us + -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 +Duration=22100us -Send Denon/Sharp variant -Protocol=Denon Address=0x12 Command=0x87 Raw-Data=0x30F2 15 bits LSB first Gap=1022100us Duration=23150us -Send with: IrSender.sendDenon(0x12, 0x87, ); +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]: - -1022100 - + 300,- 700 + 350,-1750 + 300,- 750 + 300,- 750 - + 300,-1750 + 300,-1750 + 350,-1750 + 300,-1750 - + 300,- 750 + 350,- 700 + 300,- 750 + 300,- 750 - + 300,-1750 + 350,-1700 + 350,- 700 + 350 + -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=1024150us Duration=19800us +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]: - -1024150 - +2450,- 550 - +1250,- 550 +1250,- 550 +1250,- 500 + 700,- 500 - + 650,- 550 + 700,- 500 + 650,- 550 + 650,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250 + -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=1039800us Duration=25250us +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]: - -1039800 + -743050 +2450,- 550 - +1250,- 550 +1250,- 550 +1250,- 550 + 650,- 550 + +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 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=1043550us Duration=31250us +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]: - -1043550 + -746500 +2450,- 550 +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550 - + 650,- 550 + 650,- 550 + 650,- 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 @@ -1038,227 +1052,241 @@ 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=1047950us Duration=65650us +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]: - -1047950 + -751200 +4500,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 500 - + 650 -Duration=65650us + + 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=1063650us Duration=60050us +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]: - -1063650 - +4500,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,- 500 + 650,- 450 + 650,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1650 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,-1600 + -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=1063100us Duration=87050us +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]: - -1063100 - +4500,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + -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,- 500 + 650,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 550 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,- 500 + 600,-1600 - + 650,- 500 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,-1600 + 600,- 500 + 650,-1600 + 650,- 500 + + 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=87050us +Duration=87000us Send RC5 -Protocol=RC5 Address=0x12 Command=0x7 Raw-Data=0x1487 13 bits MSB first Gap=1079600us Duration=24000us +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]: - -1079600 - + 900,- 850 - +1850,-1700 +1850,- 800 + 950,-1750 +1800,- 850 - + 950,- 800 + 950,- 850 + 900,-1750 + 950,- 850 - + 900,- 850 + 950 + -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=1038900us Duration=24050us +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]: - -1038900 + -742250 +1850,-1700 - + 950,- 850 +1800,- 850 + 900,-1750 +1850,- 800 - + 950,- 850 + 950,- 850 + 900,-1750 + 900,- 850 + + 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=1036350us Duration=22850us +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]: - -1036350 - +2700,- 850 - + 500,- 800 + 500,- 400 + 500,- 400 +1400,- 850 + -739800 + +2700,- 800 + + 500,- 850 + 500,- 400 + 500,- 400 +1400,- 850 + 500,- 400 + 450,- 400 + 500,- 400 + 500,- 850 - + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400 - + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 400 + + 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=1047550us Duration=36350us +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]: - -1047550 - +2650,- 900 - + 500,- 400 + 500,- 400 + 450,- 850 + 500,- 850 - + 950,- 400 + 950,- 850 + 450,- 400 + 950,- 450 + -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,- 450 + 450,- 450 + 450,- 400 + 500,- 850 + + 500,- 400 + 500,- 400 + 500,- 400 + 500,- 850 + 500,- 400 + 950,- 850 + 950,- 850 + 500,- 400 - + 500,- 400 + 500,- 400 +1000,- 350 + 500,- 400 - + 500 -Duration=36350us + + 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 +Send Bang&Olufsen / originally with 455 kHz - ENABLE_BEO_WITHOUT_FRAME_GAP is enabled rawData[44]: - -1061100 - + 200,-2850 - + 250,-2850 + 250,-12750 + 250,-2850 + 250,-9050 - + 250,-5950 + 300,-5900 + 300,-5950 + 250,-2850 - + 250,-5950 + 250,-9000 + 300,-2850 + 250,-9050 - + 250,-2850 + 250,-5950 + 250,-5950 + 250,-5900 - + 300,-9050 + 250,-5900 + 300,-5950 + 250,-12100 + -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=1061100us Duration=6400us +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 +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,-9050 + 250,-5950 + 300,-5900 + 300,-5950 - + 250,-2850 + 250,-5950 + 250,-9000 + 300,-2850 - + 250,-9050 + 250,-2850 + 250,-5950 + 250,-5950 - + 250,-5900 + 300,-9050 + 250,-5900 + 300,-5950 - + 250,-12100 + 250 + + 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 MagiQuest -Protocol=MagiQuest Address=0xF2 Command=0x187 Raw-Data=0x6BCD00F2 56 bits MSB first Gap=1097800us Duration=63700us -Send with: IrSender.sendMagiQuest(0x6BCD00F2, 0x187, ); -rawData[112]: - -1097800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 - + 650,- 500 + 650,- 500 + 350,- 800 + 650,- 500 - + 350,- 800 + 650,- 500 + 650,- 500 + 650,- 500 - + 650,- 500 + 350,- 800 + 350,- 800 + 650,- 500 - + 600,- 550 + 350,- 800 + 650,- 500 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 - + 300,- 800 + 350,- 800 + 350,- 800 + 650,- 500 - + 650,- 500 + 650,- 550 + 600,- 550 + 300,- 800 - + 350,- 800 + 650,- 550 + 300,- 850 + 600,- 550 - + 600,- 550 + 350,- 800 + 350,- 750 + 350,- 850 - + 300,- 800 + 650,- 500 + 650,- 500 + 650,- 550 - + 350,- 800 + 350,- 800 + 650,- 500 + 350,- 800 - + 350,- 800 + 350,- 800 + 650,- 500 + 350 -Duration=63700us - - Send next protocols with IrSender.write Send JVC -Protocol=JVC Address=0xF2 Command=0x87 Raw-Data=0x87F2 16 bits LSB first Gap=1088850us Duration=39350us +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]: - -1088850 + -804750 +8400,-4150 - + 550,- 500 + 600,-1500 + 550,- 500 + 550,- 500 - + 600,-1500 + 600,-1500 + 550,-1550 + 550,-1500 - + 600,-1550 + 550,-1500 + 600,-1500 + 600,- 450 + + 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=39350us +Duration=39400us Send LG -Protocol=LG Address=0xF2 Command=0xA987 Raw-Data=0xF2A9872 28 bits MSB first Gap=1042700us Duration=57350us +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]: - -1042700 - +8950,-4100 - + 550,-1550 + 550,-1500 + 550,-1550 + 550,-1500 - + 550,- 500 + 550,- 500 + 550,-1550 + 550,- 500 - + 550,-1500 + 550,- 500 + 550,-1550 + 550,- 500 - + 550,-1500 + 550,- 500 + 550,- 500 + 550,-1550 - + 550,-1500 + 550,- 500 + 550,- 500 + 550,- 500 - + 550,- 500 + 600,-1500 + 550,-1500 + 550,-1550 - + 550,- 500 + 550,- 500 + 550,-1500 + 550,- 500 + -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=57350us +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=1059500us Duration=26800us +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]: - -1059500 - +1050,-1450 - + 550,-1400 + 600,-1400 + 600,-1400 + 550,- 400 - + 600,- 400 + 550,- 450 + 600,- 400 + 600,-1350 - + 600,- 400 + 550,- 450 + 600,- 400 + 550,-1400 - + 600,-1400 + 550,-1400 + 600,-1450 + 550,- 400 + -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=26800us +Duration=26750us Send FAST -Protocol=FAST Address=0x0 Command=0x87 Raw-Data=0x7887 16 bits LSB first Gap=1043550us Duration=28950us +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]: - -1043550 - +2150,-1000 - + 600,-1500 + 600,-1500 + 600,-1500 + 600,- 450 - + 600,- 450 + 600,- 450 + 600,- 450 + 600,-1500 - + 600,- 450 + 600,- 450 + 550,- 500 + 600,-1500 - + 600,-1500 + 600,-1500 + 550,-1550 + 600,- 500 + -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 @@ -1267,59 +1295,59 @@ 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]: - -1042650 - + 250,- 500 - + 300,- 450 + 300,- 550 + 200,- 500 + 250,- 550 - + 250,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 250,- 500 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 250,- 500 + 300,- 450 + 300,- 450 - + 300,- 500 + 250,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 300,- 450 - + 250,- 500 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 250,- 500 + 300,- 450 - + 300,- 450 + 250,- 500 + 300,- 450 + 300,- 450 + -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 - + 300,- 450 + 250,- 500 + 300,- 450 + 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 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 250,- 550 + 250,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 300,- 450 + 300,- 450 + 300,- 450 - + 300,- 450 + 300,- 450 + 300,- 450 + 250,- 500 - + 300,- 450 + 250,- 500 + 300 -Duration=149600us + + 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 @@ -1329,398 +1357,90 @@ Start receiver address=0x1F3 command=0x98 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=1220600us Duration=67800us +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]: - -1220600 + -923500 +8950,-4400 - + 600,-1600 + 650,-1650 + 600,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,-1600 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,- 500 + 650,- 450 + 650,- 500 + 600,-1650 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + + 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 + 650,-1600 + 650,- 500 + + 650,- 500 + 600,-1600 + 600,-1650 + 600,- 550 + 600 -Duration=67800us +Duration=67850us -Protocol=NEC2 Address=0xF3 Command=0x98 Raw-Data=0x67980CF3 32 bits LSB first Repeat Gap=69200us Duration=67800us +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]: - -69200 + -68750 +8950,-4350 - + 650,-1600 + 650,-1600 + 650,- 450 + 650,- 500 + + 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,- 550 - + 600,- 500 + 600,- 500 + 650,- 500 + 600,-1650 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 - + 600 -Duration=67800us + + 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=69650us Duration=67750us +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]: - -69650 - +8900,-4400 - + 650,-1650 + 600,-1600 + 600,- 500 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,- 500 + 600,-1650 + 600,-1600 - + 650,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + -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 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500 + + 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=67750us +Duration=67850us Send NEC with 16 bit address -Protocol=NEC Address=0x1F3 Command=0x98 Raw-Data=0x679801F3 32 bits LSB first Gap=1062250us Duration=66650us +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]: - -1062250 + -765000 +8950,-4400 - + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 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 + 600,-1650 + 600,- 500 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 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=1062050us Duration=66700us +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]: - -1062050 + -764600 +8950,-4400 - + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,- 500 + 650,- 500 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,-1600 + 600,-1650 + 600,- 500 - + 650 -Duration=66700us - - -Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0x1F3 Command=0x9998 Raw-Data=0x999801F3 32 bits LSB first Gap=1062650us Duration=65600us -Send with: IrSender.sendOnkyo(0x1F3, 0x9998, ); -rawData[68]: - -1062650 - +8950,-4400 - + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 550 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 550 + 600,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,- 500 + 600,- 600 + 600,-1600 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650 -Duration=65600us - - -Send Apple -Protocol=Apple Address=0xF3 Command=0x98 Raw-Data=0xF39887EE 32 bits LSB first Gap=1061100us Duration=71150us -Send with: IrSender.sendApple(0xF3, 0x98, ); -rawData[68]: - -1061100 - +8950,-4400 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,-1650 - + 600,- 500 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,-1650 + 600,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 - + 600 -Duration=71150us - - -Send Panasonic -Protocol=Panasonic Address=0x1F3 Command=0x98 Raw-Data=0xB7981F30 48 bits LSB first Gap=1061050us Duration=62750us -Send with: IrSender.sendPanasonic(0x1F3, 0x98, ); -rawData[100]: - -1061050 - +3500,-1700 - + 450,- 400 + 500,-1250 + 450,- 450 + 450,- 350 - + 500,- 400 + 450,- 400 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 - + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,-1250 - + 450,-1250 + 500,- 350 + 500,- 400 + 450,-1250 - + 500,-1250 + 450,-1250 + 500,-1200 + 500,- 400 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1200 - + 500 -Duration=62750us - - -Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0x1F3 Command=0x98 Extra=0x4711 Raw-Data=0xB4981F33 48 bits LSB first Gap=1081300us Duration=66100us -Send with: IrSender.sendKaseikyo(0x1F3, 0x98, , 0x4711); -rawData[100]: - -1081300 - +3450,-1700 - + 450,-1250 + 500,- 350 + 500,- 400 + 500,- 350 - + 500,-1250 + 450,- 400 + 500,- 400 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,-1250 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,-1250 + 500,- 350 + 450,- 400 - + 500,-1250 + 450,-1250 + 450,- 450 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,-1250 + 500,-1250 - + 450,-1250 + 500,- 350 + 500,- 400 + 450,- 450 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,-1250 - + 500,-1250 + 450,- 400 + 500,- 350 + 500,-1250 - + 450,- 400 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 - + 500 -Duration=66100us - - -Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0x1F3 Command=0x98 Raw-Data=0xB7981F30 48 bits LSB first Gap=1082000us Duration=66150us -Send with: IrSender.sendKaseikyo_Denon(0x1F3, 0x98, ); -rawData[100]: - -1082000 - +3500,-1650 - + 500,- 400 + 500,- 350 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,- 400 + 450,-1250 + 500,- 400 - + 450,- 400 + 500,-1200 + 500,- 400 + 450,- 400 - + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,- 350 + 500,- 400 - + 450,-1250 + 450,-1300 + 450,-1250 + 500,-1250 - + 450,-1250 + 500,- 400 + 450,- 400 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 500,-1200 - + 500,-1250 + 450,- 400 + 500,- 400 + 500,-1200 - + 500,-1250 + 450,-1250 + 500,-1250 + 450,- 400 - + 500,-1200 + 500,-1250 + 450,- 400 + 500,-1250 - + 450 -Duration=66150us - - -Send Denon -Protocol=Denon Address=0x13 Command=0x98 Raw-Data=0x1313 15 bits LSB first Gap=1079800us Duration=22100us -Send with: IrSender.sendDenon(0x13, 0x98, ); -rawData[32]: - -1079800 - + 300,-1750 + 350,-1750 + 300,- 750 + 300,- 700 - + 350,-1750 + 300,- 750 + 300,- 700 + 350,- 700 - + 350,-1750 + 300,-1750 + 300,- 750 + 300,- 750 - + 300,-1750 + 350,- 700 + 350,- 700 + 300 -Duration=22100us - - -Send Denon/Sharp variant -Protocol=Denon Address=0x13 Command=0x98 Raw-Data=0x3313 15 bits LSB first Gap=1022100us Duration=23100us -Send with: IrSender.sendDenon(0x13, 0x98, ); -rawData[32]: - -1022100 - + 300,-1750 + 300,-1750 + 350,- 700 + 350,- 700 - + 350,-1700 + 350,- 700 + 350,- 700 + 350,- 700 - + 300,-1750 + 350,-1750 + 300,- 700 + 350,- 700 - + 350,-1750 + 300,-1750 + 350,- 750 + 250 -Duration=23100us - - -Send Sony/SIRCS with 7 command and 5 address bits -Protocol=Sony Address=0x13 Command=0x18 Raw-Data=0x998 12 bits LSB first Gap=1024150us Duration=19850us -Send with: IrSender.sendSony(0x13, 0x18, 2, 12); -rawData[26]: - -1024150 - +2450,- 550 - + 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250 -Duration=19850us - - -Send Sony/SIRCS with 7 command and 8 address bits -Protocol=Sony Address=0xF3 Command=0x18 Raw-Data=0x7998 15 bits LSB first Gap=1040000us Duration=25200us -Send with: IrSender.sendSony(0xF3, 0x18, 2, 15); -rawData[32]: - -1040000 - +2400,- 550 - + 700,- 500 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 +1250,- 550 +1250 -Duration=25200us - - -Send Sony/SIRCS with 7 command and 13 address bits -Protocol=Sony Address=0x1F3 Command=0x18 Raw-Data=0xF998 20 bits LSB first Gap=1043700us Duration=31850us -Send with: IrSender.sendSony(0x1F3, 0x18, 2, 20); -rawData[42]: - -1043700 - +2450,- 550 - + 650,- 550 + 700,- 500 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 + 650,- 550 + 650,- 550 +1250,- 550 - +1250,- 550 +1250,- 550 +1300,- 500 +1250,- 550 - + 650,- 550 + 650,- 550 + 650,- 550 + 650 -Duration=31850us - - -Send Samsung 8 bit command and 8 bit address -Protocol=Samsung Address=0xF3 Command=0x98 Raw-Data=0x6798F3F3 32 bits LSB first Gap=1048300us Duration=67800us -Send with: IrSender.sendSamsung(0xF3, 0x98, ); -rawData[68]: - -1048300 - +4450,-4400 - + 650,-1600 + 650,-1600 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,- 450 + 650,- 500 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,-1650 + 600,-1600 + 650,- 500 - + 600 -Duration=67800us - - -Send Samsung 16 bit command and address -Protocol=Samsung Address=0x1F3 Command=0xBA98 Raw-Data=0xBA9801F3 32 bits LSB first Gap=1063700us Duration=62250us -Send with: IrSender.sendSamsung(0x1F3, 0xBA98, ); -rawData[68]: - -1063700 - +4500,-4400 + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 550 + 600,- 500 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,- 500 + 650,-1600 - + 600,-1650 + 600,-1600 + 650,- 500 + 600,-1600 - + 650 -Duration=62250us - - -Send Samsung48 16 bit command -Protocol=Samsung48 Address=0x1F3 Command=0xBA98 Raw-Data=0x45BA 48 bits LSB first Gap=1063250us Duration=89200us -Send with: IrSender.sendSamsung48(0x1F3, 0xBA98, ); -rawData[100]: - -1063250 - +4500,-4400 - + 650,-1600 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 550 + 600,- 500 + 600,-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 - + 650,- 500 + 600,-1600 + 650,- 500 + 600,-1650 - + 600,-1600 + 650,-1600 + 650,- 500 + 600,-1600 - + 650,-1600 + 650,- 500 + 600,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,-1600 + 650,- 500 - + 600 -Duration=89200us - - -Send RC5 -Protocol=RC5 Address=0x13 Command=0x18 Toggle=1 Raw-Data=0x1CD8 13 bits MSB first Gap=1079850us Duration=23100us -Send with: IrSender.sendRC5(0x13, 0x18, ); -rawData[22]: - -1079850 - + 950,- 800 - + 950,- 850 + 900,- 850 +1850,- 850 + 900,-1750 - + 950,- 850 +1800,-1700 + 950,- 850 +1800,- 850 - + 950,- 800 + 950 -Duration=23100us - - -Send RC5X with 7.th MSB of command set -Protocol=RC5 Address=0x13 Command=0x58 Raw-Data=0x4D8 13 bits MSB first Gap=1040700us Duration=23100us -Send with: IrSender.sendRC5(0x13, 0x58, ); -rawData[20]: - -1040700 - +1800,- 850 - + 950,-1700 +1850,- 800 + 950,-1750 + 900,- 850 - +1850,-1700 + 950,- 850 +1800,- 850 + 900,- 850 - + 950 -Duration=23100us - - -Send RC6 -Protocol=RC6 Address=0xF3 Command=0x98 Raw-Data=0xF398 20 bits MSB first Gap=1035450us Duration=23300us -Send with: IrSender.sendRC6(0xF3, 0x98, ); -rawData[38]: - -1035450 - +2700,- 850 - + 500,- 800 + 500,- 400 + 500,- 400 + 500,- 850 - +1400,- 400 + 450,- 400 + 500,- 400 + 500,- 850 - + 500,- 400 + 950,- 400 + 500,- 400 + 500,- 850 - + 500,- 400 + 950,- 400 + 500,- 850 + 500,- 400 - + 500,- 400 + 500 -Duration=23300us - - -Send RC6A with 14 bit 0x2711 as extra -Protocol=RC6A Address=0xF3 Command=0x98 Extra=0x2711 Toggle=1 Raw-Data=0xA711F398 35 bits MSB first Gap=1047300us Duration=36800us -Send with: IrSender.sendRC6A(0xF3, 0x98, , 0x2711); -rawData[60]: - -1047300 - +2700,- 850 - + 500,- 400 + 450,- 450 + 500,- 800 +1400,-1300 - + 950,- 850 + 500,- 400 + 950,- 400 + 450,- 400 - + 500,- 900 + 450,- 400 + 500,- 400 + 950,- 850 - + 500,- 400 + 500,- 400 + 950,- 400 + 500,- 450 - + 450,- 450 + 450,- 450 + 450,- 850 + 500,- 400 - + 950,- 450 + 450,- 450 + 450,- 850 + 500,- 400 - + 950,- 400 + 500,- 850 + 500,- 400 + 500,- 400 - + 500 -Duration=36800us - - -Send Bang&Olufsen -- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled -rawData[44]: - -1061400 - + 300,-2800 - + 250,-2850 + 250,-12750 + 300,-2850 + 200,-9050 - + 300,-5950 + 250,-5950 + 250,-5950 + 250,-2850 - + 250,-5950 + 250,-9000 + 300,-5950 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-9050 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-5950 + 250,-12100 - + 300 -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=1061400us 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=0xF3 Command=0x98 Raw-Data=0xF398 16 bits MSB first Gap=12750us Duration=115000us -Send with: IrSender.sendBang&Olufsen(0xF3, 0x98, ); -rawData[38]: - -12750 - + 300,-2850 - + 200,-9050 + 300,-5950 + 250,-5950 + 250,-5950 - + 250,-2850 + 250,-5950 + 250,-9000 + 300,-5950 - + 250,-5950 + 250,-2850 + 250,-5950 + 250,-9050 - + 250,-5950 + 250,-2850 + 250,-5950 + 250,-5950 - + 250,-12100 + 300 -Duration=115000us + + 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/keywords.txt b/keywords.txt index a67cd0ed8..5f05f9d1a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -140,7 +140,6 @@ IRDATA_FLAGS_IS_MSB_FIRST LITERAL1 RAW_BUFFER_LENGTH LITERAL1 EXCLUDE_UNIVERSAL_PROTOCOLS LITERAL1 EXCLUDE_EXOTIC_PROTOCOLS LITERAL1 -DECODE_STRICT_CHECKS LITERAL1 IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK LITERAL1 MARK_EXCESS_MICROS LITERAL1 RECORD_GAP_MICROS LITERAL1 diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 4331b0d6f..c556c4df2 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -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! @@ -100,35 +153,7 @@ 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 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 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[DECODED_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(), 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. -}; +#define IRDATA_FLAGS_LSB_MSB_FIRST_MASK IRDATA_FLAGS_IS_MSB_FIRST extern uint8_t sLastSendToggleValue; // Currently used by RC5 + RC6 @@ -144,11 +169,14 @@ struct PulseDistanceWidthProtocolConstants { /* * Definitions for member PulseDistanceWidthProtocolConstants.Flags */ -#define PROTOCOL_IS_PULSE_DISTANCE 0x00 -#define PROTOCOL_IS_PULSE_WIDTH 0x10 -#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 @@ -171,10 +199,7 @@ const __FlashStringHelper* getProtocolString(decode_type_t aProtocol); #else const char* getProtocolString(decode_type_t aProtocol); #endif -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); + /* * Convenience functions to convert MSB to LSB values */ diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 477c01a26..591c21f2d 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -150,173 +150,6 @@ namespace PrintULL { # endif #endif -/** @} - * \addtogroup Print Print functions - * @{ - */ -/** - * 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. - * - */ -void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) { - // DEPRECATED - - (void) aPrintRepeatGap; - printIRDataShort(aSerial, aIRDataPtr); -} - -/* - * 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 - */ -void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { - 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 - } -} - /** @} * \addtogroup Utils Utility functions * @{ diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index da36756ab..b6cea9e87 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 @@ -34,7 +34,7 @@ #define _IR_RECEIVE_HPP #if defined(DEBUG) -//#define LOCAL_DEBUG // +#define LOCAL_DEBUG #else //#define LOCAL_DEBUG // This enables debug output only for this file #endif @@ -686,7 +686,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; } @@ -732,58 +732,60 @@ 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! - * Timing check of +/- 25 percent by matchSpace() or matchMark(). + * 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.irparams.rawbuf[] * Output is IrReceiver.decodedIRData.decodedRawData * - * Assume PULSE_DISTANCE if aOneMarkMicros == aZeroMarkMicros - * - * @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 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 = &irparams.rawbuf[aStartOffset]; - - // Assume PULSE_DISTANCE if aOneMarkMicros == aZeroMarkMicros - 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--) { - bool tBitValue; - if (isPulseDistanceProtocol) { + bool tBitValue; + uint16_t tCurrentTicks; + if (aIsPulseWidthProtocol) { /* - * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here. - * !!!We only check variable length space indicating a 1 or 0!!! + * 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++; - unsigned int 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. - * !!!We only check variable length mark indicating a 1 or 0!!! + * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here. + * !!!We only check variable length space indicating a 1 or 0!!! */ - unsigned int tMarkTicks = *tRawBufPointer++; - tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 tRawBufPointer++; + 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) { @@ -797,67 +799,61 @@ bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } else { tDecodedData |= tMask; } - IR_TRACE_PRINTLN(F("=> 1")); + IR_TRACE_PRINT(tCurrentTicks); + IR_TRACE_PRINTLN(F(" => 1")); } else { // do not set the bit - IR_TRACE_PRINTLN(F("=> 0")); + IR_TRACE_PRINT(tCurrentTicks); + IR_TRACE_PRINTLN(F(" => 0")); } tMask <<= 1; } decodedIRData.decodedRawData = tDecodedData; - return true; } /** - * 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! - * - * 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 using the PULSE_DISTANCE decoding. - * - * Input is IrReceiver.irparams.rawbuf[] - * Output is IrReceiver.decodedIRData.decodedRawData - * - * @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 0 or 1 - * @param aIsPulseDistanceProtocol - * @param aMSBfirst If true send Most Significant Bit first, else send Least Significant Bit (lowest bit) first. - * @return true assume always successful decoding - */ -/* - * Experimental threshold decoder to be activated by USE_THRESHOLD_DECODING - * I hope that this will give better results for noisy signals and protocols with short pulses/ pauses - * Currently experimental and requires up to 310 bytes more program space, if more than 1 protocol is involved + * 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. */ -//#define USE_THRESHOLD_DECODING -bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneThresholdMicros, - bool aIsPulseDistanceProtocol, bool aMSBfirst) { +void IRrecv::decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, + uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst) { - auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; +#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--) { - uint16_t tOneThresholdMicros; - if (aIsPulseDistanceProtocol) { - /* - * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here. - * !!!We only check variable length space indicating a 1 or 0!!! - */ + if (!aIsPulseWidthProtocol) { tRawBufPointer++; - tOneThresholdMicros = aOneThresholdMicros - MARK_EXCESS_MICROS; - } else { - tOneThresholdMicros = aOneThresholdMicros + MARK_EXCESS_MICROS; } - unsigned int tCurrentTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) - bool tBitValue = ((tCurrentTicks * MICROS_PER_TICK) > tOneThresholdMicros); // Check for variable length space indicating a 1 or 0 + uint16_t tCurrentMicros = *tRawBufPointer * MICROS_PER_TICK; + bool tBitValue = tCurrentMicros > aOneThresholdMicros; // Check for variable length timing indicating a 1 or 0 + tRawBufPointer++; - if (!aIsPulseDistanceProtocol) { + if (aIsPulseWidthProtocol) { tRawBufPointer++; } @@ -872,46 +868,52 @@ 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 = &irparams.rawbuf[aStartOffset]; - bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol + + 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 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) { /* - * 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++; - unsigned int tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-) + 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!!! */ - unsigned int tMarkTicks = *tRawBufPointer++; + tMarkTicks = *tRawBufPointer++; tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0 tRawBufPointer++; } @@ -935,17 +937,27 @@ 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) { @@ -1073,39 +1085,42 @@ 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, +void IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) { -#if defined(USE_THRESHOLD_DECODING) - /* - * I hope that this will give better results for noisy signals and protocols with short pulses/ pauses - * Still experimental and requires up to 310 bytes more program space, if more than 1 protocol is involved - * but saves 90 bytes if only e.g. NEC is selected. - */ - bool tIsPulseDistanceProtocol = aProtocolConstants->Flags & PROTOCOL_IS_PULSE_DISTANCE; - uint16_t tOneThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros; - if (tIsPulseDistanceProtocol) { - tOneThresholdMicros = (aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros - + aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros) / 2; + + 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 { - tOneThresholdMicros = (aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros - + aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros) / 2; + // 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 decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, tOneThresholdMicros, tIsPulseDistanceProtocol, - (aProtocolConstants->Flags & PROTOCOL_IS_MSB_FIRST)); + return decodeWithThresholdPulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros, + aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK)); #else - return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, - aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, - (aProtocolConstants->Flags & PROTOCOL_IS_MSB_FIRST)); + 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 } -bool IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, +void IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, sizeof(tTemporaryPulseDistanceWidthProtocolConstants)); - return decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset); + decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset); } /* @@ -1295,14 +1310,14 @@ bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolC // Check header "mark" and "space" if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); + Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); Serial.println(F(": Header mark length is wrong")); #endif return false; } if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString(aProtocolConstantsPGM->ProtocolIndex)); + Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); Serial.println(F(": Header space length is wrong")); #endif return false; @@ -1327,20 +1342,25 @@ 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("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, DEC); + Serial.print(aMeasuredTicks * MICROS_PER_TICK); Serial.print(F(" <= ")); - Serial.print(TICKS_HIGH(aMatchValueMicros), DEC); + Serial.print(tMatchValueMicrosQuarter * 5); #endif - bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros))); + bool passed = (tMeasuredMicros >= (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5)); #if defined(LOCAL_TRACE) if (passed) { Serial.println(F(" => passed")); @@ -1351,6 +1371,35 @@ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { return passed; } +/** + * 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); } @@ -1360,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) +#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, DEC); + Serial.print(aMeasuredTicks * MICROS_PER_TICK); Serial.print(F("us vs ")); - Serial.print(aMatchValueMicros, DEC); + Serial.print(aMatchValueMicros); Serial.print(F("us: ")); - Serial.print(TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); +// 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, DEC); + Serial.print(aMeasuredTicks * MICROS_PER_TICK); Serial.print(F(" <= ")); - Serial.print(TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); -#endif + Serial.print(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK); +# 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) + 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 +# endif return passed; +#endif } bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) { @@ -1394,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) +#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, DEC); + Serial.print(aMeasuredTicks * MICROS_PER_TICK); Serial.print(F("us vs ")); - Serial.print(aMatchValueMicros, DEC); + Serial.print(aMatchValueMicros); Serial.print(F("us: ")); - Serial.print(TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); + 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, DEC); + Serial.print(aMeasuredTicks * MICROS_PER_TICK); Serial.print(F(" <= ")); - Serial.print(TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC); -#endif + Serial.print(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK); +# 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) + 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 +# endif return passed; +#endif } bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) { @@ -1530,6 +1605,11 @@ void printActiveIRProtocols(Print *aSerial) { #endif } +/** @} + * \addtogroup Print Print functions + * @{ + */ + /** * Function to print values and flags of IrReceiver.decodedIRData in one line. * Ends with println(). @@ -1564,7 +1644,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) #endif #if !defined(DISABLE_CODE_FOR_RECEIVER) aSerial->print(' '); - aSerial->print((decodedIRData.rawlen + 1) / 2, DEC); + aSerial->print((decodedIRData.rawlen + 1) / 2); aSerial->println(F(" bits (incl. gap and start) received")); #endif } else { @@ -1577,20 +1657,20 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) aSerial->print(F(" Address=0x")); aSerial->print(decodedIRData.address, HEX); - aSerial->print(F(" Command=0x")); + aSerial->print(F(", Command=0x")); aSerial->print(decodedIRData.command, HEX); if (tFlags & IRDATA_FLAGS_EXTRA_INFO) { - aSerial->print(F(" Extra=0x")); + aSerial->print(F(", Extra=0x")); aSerial->print(decodedIRData.extra, HEX); } if (tFlags & IRDATA_FLAGS_PARITY_FAILED) { - aSerial->print(F(" Parity fail")); + aSerial->print(F(", Parity fail")); } if (tFlags & IRDATA_FLAGS_TOGGLE_BIT) { - aSerial->print(F(" Toggle=1")); + aSerial->print(F(", Toggle=1")); } #if defined(DECODE_DISTANCE_WIDTH) } @@ -1600,18 +1680,19 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) * Print raw data, numberOfBits and MSB or LSB */ if (!(tFlags & IRDATA_FLAGS_IS_REPEAT) || decodedIRData.decodedRawData != 0) { - aSerial->print(F(" Raw-Data=0x")); + 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(' '); - aSerial->print(decodedIRData.numberOfBits, DEC); - aSerial->print(F(" bits")); + aSerial->print(decodedIRData.numberOfBits); + aSerial->print(F(" bits,")); if (tFlags & IRDATA_FLAGS_IS_MSB_FIRST) { aSerial->print(F(" MSB first")); @@ -1624,14 +1705,14 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) * 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(' '); + 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(F(", Gap=")); aSerial->print((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK); aSerial->print(F("us")); @@ -1642,8 +1723,8 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { tSumOfDurationTicks += irparams.rawbuf[i]; } - aSerial->print(F(" Duration=")); - aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->print(F(", Duration=")); + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK); aSerial->println(F("us")); #else aSerial->println(); @@ -1658,6 +1739,167 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) 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(", ")); @@ -1872,7 +2114,7 @@ void IRrecv::printIRResultMinimal(Print *aSerial) { # endif #endif aSerial->print(' '); - aSerial->print((decodedIRData.rawlen + 1) / 2, DEC); + aSerial->print((decodedIRData.rawlen + 1) / 2); aSerial->println(F(" bits received")); } else { /* @@ -1907,11 +2149,11 @@ void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTi } aSerial->print(F("Duration=")); if (aOutputMicrosecondsInsteadOfTicks) { - aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK); aSerial->println(F("us")); } else { - aSerial->print(tSumOfDurationTicks, DEC); + aSerial->print(tSumOfDurationTicks); aSerial->println(F(" ticks")); } } @@ -1926,7 +2168,7 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI // Print Raw data aSerial->print(F("rawData[")); - aSerial->print(decodedIRData.rawlen, DEC); + aSerial->print(decodedIRData.rawlen); aSerial->println(F("]: ")); /* @@ -1934,9 +2176,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 @@ -1983,7 +2225,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 @@ -1998,11 +2240,11 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI aSerial->println(); aSerial->print(F("Duration=")); if (aOutputMicrosecondsInsteadOfTicks) { - aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC); + aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK); aSerial->println(F("us")); } else { - aSerial->print(tSumOfDurationTicks, DEC); + aSerial->print(tSumOfDurationTicks); aSerial->println(F(" ticks")); } aSerial->println(); @@ -2012,15 +2254,19 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI /** * 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 @@ -2028,18 +2274,20 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr 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 = 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) { @@ -2070,7 +2318,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr /** * 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). @@ -2097,6 +2345,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) { diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 756af9d9c..a47055703 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -407,6 +407,10 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma return 1; } +/********************************************************************************************************************** + * SendRaw functions + **********************************************************************************************************************/ + /** * Sends a 16 byte microsecond timing array. * Raw data starts with a Mark. No leading space as in received timing data! @@ -516,22 +520,155 @@ void IRsend::sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast16_t aLengthOf #endif } +/********************************************************************************************************************** + * 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, @@ -668,6 +805,27 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint } } +/********************************************************************************************************************** + * 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) { @@ -678,6 +836,74 @@ void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz, aRepeatPeriodMillis, aNumberOfRepeats); } +/********************************************************************************************************************** + * Send functions with PulseDistanceWidthProtocolConstants parameter + **********************************************************************************************************************/ +/** + * Sends PulseDistance frames and repeats + * @param aProtocolConstants The constants to use for sending this protocol. + * @param aData uint32 or uint64 holding the bits to be sent. + * @param aNumberOfBits Number of bits from aData to be actually sent. + * @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified + * then it is called without leading and trailing space. + */ +void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, + uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { + +#if defined(LOCAL_DEBUG) + Serial.print(F("Data=0x")); + Serial.print(aData, HEX); + Serial.print(F(" #=")); + Serial.println(aNumberOfBits); + Serial.flush(); +#endif + + if (aNumberOfRepeats < 0) { + if (aProtocolConstants->SpecialSendRepeatFunction != nullptr) { + /* + * Send only a special repeat and return + */ + aProtocolConstants->SpecialSendRepeatFunction(); + return; + } else { + // Send only one plain frame (as repeat) + aNumberOfRepeats = 0; + } + } + + // Set IR carrier frequency + enableIROut(aProtocolConstants->FrequencyKHz); + + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; + while (tNumberOfCommands > 0) { + unsigned long tStartOfFrameMillis = millis(); + + 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 { + /* + * Send Header and regular frame + */ + mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros); + space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros); + sendPulseDistanceWidthData(aProtocolConstants, aData, aNumberOfBits); + } + + 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 (aProtocolConstants->RepeatPeriodMillis > tCurrentFrameDurationMillis) { + delay(aProtocolConstants->RepeatPeriodMillis - tCurrentFrameDurationMillis); + } + } + } +} + /** * 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. @@ -761,25 +987,6 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants } } -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::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { @@ -859,214 +1066,35 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta } } -/** - * Sends PulseDistance frames and repeats - * @param aProtocolConstants The constants to use for sending this protocol. - * @param aData uint32 or uint64 holding the bits to be sent. - * @param aNumberOfBits Number of bits from aData to be actually sent. - * @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified - * then it is called without leading and trailing space. - */ -void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, - uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { - -#if defined(LOCAL_DEBUG) - Serial.print(F("Data=0x")); - Serial.print(aData, HEX); - Serial.print(F(" #=")); - Serial.println(aNumberOfBits); - Serial.flush(); -#endif - - if (aNumberOfRepeats < 0) { - if (aProtocolConstants->SpecialSendRepeatFunction != nullptr) { - /* - * Send only a special repeat and return - */ - aProtocolConstants->SpecialSendRepeatFunction(); - return; - } else { - // Send only one plain frame (as repeat) - aNumberOfRepeats = 0; - } - } - - // Set IR carrier frequency - enableIROut(aProtocolConstants->FrequencyKHz); - - uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; - while (tNumberOfCommands > 0) { - unsigned long tStartOfFrameMillis = millis(); +/********************************************************************************************************************** + * Stubs for send functions with PulseDistanceWidthProtocolConstants parameter + **********************************************************************************************************************/ - 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 { - /* - * Send Header and regular frame - */ - mark(aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros); - space(aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros); - sendPulseDistanceWidthData(aProtocolConstants, aData, aNumberOfBits); - } +void IRsend::sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, + IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { - 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 (aProtocolConstants->RepeatPeriodMillis > tCurrentFrameDurationMillis) { - delay(aProtocolConstants->RepeatPeriodMillis - tCurrentFrameDurationMillis); - } - } - } -} -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 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); - } - } - } -} - -/** - * 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); + sendPulseDistanceWidthFromArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataArray, aNumberOfBits, + aNumberOfRepeats); } - -void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, - uint_fast8_t aNumberOfBits) { +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)); - sendPulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aData, aNumberOfBits); + sendPulseDistanceWidthFromPGMArray(&tTemporaryPulseDistanceWidthProtocolConstants, aDecodedRawDataPGMArray, aNumberOfBits, + aNumberOfRepeats); } -/** - * 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) { - -#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_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'); -#endif - mark(aZeroMarkMicros); - space(aZeroSpaceMicros); - } - if (aFlags & PROTOCOL_IS_MSB_FIRST) { - 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 +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); } /** diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 942e9aba6..fac095a63 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -54,6 +54,7 @@ * - 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. @@ -74,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. @@ -143,8 +91,6 @@ * At 100 us it also worked, but not as well. * Set MARK_EXCESS to 100 us and the VS1838 doesn't work at all. * - * The right value is critical for IR codes using short pulses like Denon / Sharp / Lego - * * Observed values: * Delta of each signal type is around 50 up to 100 us and at low signals up to 200 us. * TSOP is better, especially at low IR signal level. @@ -152,8 +98,12 @@ * TSOP31238 Mark Excess 0 to +50 */ #if !defined(MARK_EXCESS_MICROS) +# 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 +#define MARK_EXCESS_MICROS 20 // a value != 0 requires up to 100 bytes program space +# endif #endif /** diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index c373eb81d..f0daeddd9 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -149,7 +149,34 @@ struct irparams_struct { extern unsigned long sMicrosAtLastStopTimer; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer() -#include "IRProtocol.h" +#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 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[DECODED_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(), 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 @@ -279,6 +306,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); @@ -291,19 +319,22 @@ class IRrecv { /* * The main decoding functions used by the individual decoders */ - bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, + void decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset = 3); - bool decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, + void decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset = 3); - bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, - uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst); + void decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMicros, + bool aIsPulseWidthProtocol, bool aMSBfirst); - bool decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneThresholdMicros, - bool aIsPulseDistanceProtocol, bool aMSBfirst); + void decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, + uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, 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 aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst); + + 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."))); @@ -389,12 +420,18 @@ class IRrecv { 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); @@ -439,8 +476,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.)) diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index 455eb85f7..b278d1f0c 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -47,7 +47,7 @@ #define BOSEWAVE_MAXIMUM_REPEAT_DISTANCE 62000 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 + 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}; /************************************ @@ -76,13 +76,7 @@ bool IRrecv::decodeBoseWave() { return false; } - if (!decodePulseDistanceWidthData_P(&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(irparams.rawbuf[3 + (2 * BOSEWAVE_BITS)], BOSEWAVE_BIT_MARK)) { diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index 7e47a2c85..69827fefb 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -106,7 +106,7 @@ #define DENON_HEADER_SPACE (3 * DENON_UNIT) // 780 // The length of the Header:Space 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, + 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}; /************************************ @@ -138,7 +138,7 @@ void IRsend::sendDenon(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOf 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) { @@ -179,15 +179,9 @@ bool IRrecv::decodeDenon() { } // Try to decode as Denon protocol - if (!decodePulseDistanceWidthData_P(&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 + // 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: ")); @@ -204,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; @@ -308,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 16541aeda..d7a7a9cd8 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -67,6 +67,7 @@ #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) @@ -209,10 +210,12 @@ bool IRrecv::decodeDistanceWidth() { * 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; } @@ -231,7 +234,7 @@ bool IRrecv::decodeDistanceWidth() { 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); @@ -256,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 @@ -278,7 +281,7 @@ bool IRrecv::decodeDistanceWidth() { 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); @@ -303,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(tNumberOfBits); + Serial.print(F(", ")); Serial.print(irparams.rawbuf[1] * MICROS_PER_TICK); Serial.print(F(", ")); Serial.print(irparams.rawbuf[2] * MICROS_PER_TICK); Serial.print(F(", ")); - Serial.print(tMarkTicksLong * MICROS_PER_TICK); + if(tMarkTicksLong == 0) { + Serial.print(tMarkTicksShort * MICROS_PER_TICK); + } else { + Serial.print(tMarkTicksLong * MICROS_PER_TICK); + } Serial.print(F(", ")); - Serial.print(tSpaceTicksLong * MICROS_PER_TICK); + 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; @@ -385,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")); diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index e01f98296..81c7281a3 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -64,9 +64,8 @@ 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, (FAST_REPEAT_PERIOD - / MICROS_IN_ONE_MILLI), nullptr }; +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 @@ -113,14 +112,7 @@ bool IRrecv::decodeFAST() { return false; } - if (!decodePulseDistanceWidthData_P(&FASTProtocolConstants, FAST_BITS)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("FAST: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } - + decodePulseDistanceWidthData_P(&FASTProtocolConstants, FAST_BITS); WordUnion tValue; tValue.UWord = decodedIRData.decodedRawData; @@ -128,7 +120,7 @@ bool IRrecv::decodeFAST() { #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 ee34df1e9..500b91641 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -81,7 +81,7 @@ #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 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, (JVC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; + 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 @@ -153,15 +153,8 @@ bool IRrecv::decodeJVC() { return false; } - if (!decodePulseDistanceWidthData_P(&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 @@ -208,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 9abce660c..fa1086851 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -119,7 +119,7 @@ #define JVC_VENDOR_ID_CODE 0x0103 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 + 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}; /************************************ @@ -213,13 +213,7 @@ bool IRrecv::decodeKaseikyo() { } // decode first 16 Vendor ID bits - if (!decodePulseDistanceWidthData_P(&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_P(&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 02e7a6e34..28c04c654 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -115,10 +115,10 @@ //#define LG_REPEAT_DISTANCE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms 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, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendNECSpecialRepeat}; + 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 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, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendLG2SpecialRepeat}; + 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 @@ -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); @@ -208,8 +209,7 @@ bool IRrecv::decodeLG() { // Check for repeat - here we have another header space length if (decodedIRData.rawlen == 4) { - if (matchSpace(irparams.rawbuf[2], LG_REPEAT_HEADER_SPACE) - && matchMark(irparams.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; @@ -232,13 +232,7 @@ bool IRrecv::decodeLG() { return false; } - if (!decodePulseDistanceWidthData_P(&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; @@ -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 2cee82734..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 +// 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, (LEGO_AUTO_REPEAT_PERIOD_MIN - / MICROS_IN_ONE_MILLI), nullptr }; +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,7 +149,11 @@ 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; } @@ -140,18 +166,16 @@ bool IRrecv::decodeLegoPowerFunctions() { 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(irparams.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 f2d8fa08a..3517fb694 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -93,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 @@ -107,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 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 | SUPPRESS_STOP_BIT, 110, -nullptr }; +// 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}; //+============================================================================= // /** @@ -164,14 +166,13 @@ bool IRrecv::decodeMagiQuest() { /* * Check for 8 zero header bits */ - if (!decodePulseDistanceWidthData_P(&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")); @@ -183,13 +184,11 @@ bool IRrecv::decodeMagiQuest() { /* * Decode the 31 bit ID */ - if (!decodePulseDistanceWidthData_P(&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; uint32_t tWandId = decodedIRData.decodedRawData; // save tWandId for later use tDecodedRawData.ULong = decodedIRData.decodedRawData << 1; // shift for checksum computation @@ -203,14 +202,13 @@ bool IRrecv::decodeMagiQuest() { /* * Decode the 9 bit Magnitude + 8 bit checksum */ - if (!decodePulseDistanceWidthData_P(&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 4c5c83841..e70c87c88 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -116,12 +116,12 @@ #define APPLE_ADDRESS 0x87EE struct PulseDistanceWidthProtocolConstants const NECProtocolConstants PROGMEM = {NEC, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, - NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), - &sendNECSpecialRepeat}; + NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), + &sendNECSpecialRepeat}; // Like NEC but repeats are full frames instead of special NEC repeats struct PulseDistanceWidthProtocolConstants const NEC2ProtocolConstants PROGMEM = {NEC2, NEC_KHZ, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, - NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; + NEC_ONE_SPACE, NEC_BIT_MARK, NEC_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; /************************************ * Start of send and decode functions @@ -276,14 +276,8 @@ bool IRrecv::decodeNEC() { return false; } - // Try to decode as NEC protocol - if (!decodePulseDistanceWidthData_P(&NECProtocolConstants, NEC_BITS)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("NEC: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } + // Decode as NEC protocol + decodePulseDistanceWidthData_P(&NECProtocolConstants, NEC_BITS); // Success // decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value @@ -292,7 +286,7 @@ bool IRrecv::decodeNEC() { decodedIRData.command = tValue.UByte.MidHighByte; // 8 bit #if defined(DECODE_ONKYO) - // Here only Onkyo protocol is supported -> force 16 bit address and command decoding + // Here only Onkyo protocol is supported -> force 16 bit address and command decoding. No NEC decoding possible! decodedIRData.address = tValue.UWord.LowWord; // first 16 bit decodedIRData.protocol = ONKYO; decodedIRData.command = tValue.UWord.HighWord; // 16 bit command @@ -379,13 +373,7 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("NEC MSB: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } + decodePulseDistanceWidthData(NEC_BITS, offset, NEC_BIT_MARK, NEC_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST); // Stop bit if (!matchMark(aResults->rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) { diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index 20e4cc62c..6db70fc32 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -59,7 +59,7 @@ #define DISH_REPEAT_SPACE 6200 // really? struct PulseDistanceWidthProtocolConstants const DishProtocolConstants PROGMEM = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, -DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 40, nullptr }; +DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 40, nullptr }; void IRsend::sendDish(uint16_t aData) { sendPulseDistanceWidth_P(&DishProtocolConstants, aData, DISH_BITS, 4); @@ -85,7 +85,7 @@ void IRsend::sendDish(uint16_t aData) { #define WHYNTER_ZERO_SPACE 750 struct PulseDistanceWidthProtocolConstants const WhynterProtocolConstants PROGMEM = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, -WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST, 110, nullptr }; +WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 110, nullptr }; void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) { sendPulseDistanceWidth_P(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend); @@ -99,10 +99,8 @@ bool IRrecv::decodeWhynter() { if (!checkHeader_P(&WhynterProtocolConstants)) { return false; } - if (!decodePulseDistanceWidthData_P(&WhynterProtocolConstants, WHYNTER_BITS)) { - return false; - } - // Success + decodePulseDistanceWidthData_P(&WhynterProtocolConstants, WHYNTER_BITS); + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; decodedIRData.numberOfBits = WHYNTER_BITS; decodedIRData.protocol = WHYNTER; diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 58b285df6..46ec5d550 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -103,11 +103,11 @@ // 19 byte RAM struct PulseDistanceWidthProtocolConstants const SamsungProtocolConstants PROGMEM = {SAMSUNG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, - SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, + SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr}; struct PulseDistanceWidthProtocolConstants const SamsungLGProtocolConstants PROGMEM = {SAMSUNGLG, SAMSUNG_KHZ, SAMSUNG_HEADER_MARK, - SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST, + SAMSUNG_HEADER_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, SAMSUNG_BIT_MARK, SAMSUNG_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (SAMSUNG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendSamsungLGSpecialRepeat}; /************************************ * Start of send and decode functions @@ -298,13 +298,7 @@ bool IRrecv::decodeSamsung() { /* * Decode first 32 bits */ - if (!decodePulseDistanceWidthData_P(&SamsungProtocolConstants, SAMSUNG_BITS, 3)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("Samsung: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } + decodePulseDistanceWidthData_P(&SamsungProtocolConstants, SAMSUNG_BITS, 3); LongUnion tValue; tValue.ULong = decodedIRData.decodedRawData; decodedIRData.address = tValue.UWord.LowWord; @@ -314,14 +308,8 @@ bool IRrecv::decodeSamsung() { * Samsung48 */ // decode additional 16 bit - if (!decodePulseDistanceWidthData_P(&SamsungProtocolConstants, (SAMSUNG_COMMAND32_BITS - SAMSUNG_COMMAND16_BITS), - 3 + (2 * SAMSUNG_BITS))) { -#if defined(LOCAL_DEBUG) - Serial.print(F("Samsung: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } + decodePulseDistanceWidthData_P(&SamsungProtocolConstants, (SAMSUNG_COMMAND32_BITS - SAMSUNG_COMMAND16_BITS), + 3 + (2 * SAMSUNG_BITS)); /* * LSB data is already in tValue.UWord.HighWord! @@ -401,11 +389,8 @@ bool IRrecv::decodeSAMSUNG(decode_results *aResults) { } offset++; - if (!decodePulseDistanceWidthData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST)) { - return false; - } + decodePulseDistanceWidthData(SAMSUNG_BITS, offset, SAMSUNG_BIT_MARK, SAMSUNG_ONE_SPACE, 0, PROTOCOL_IS_MSB_FIRST); - // Success aResults->value = decodedIRData.decodedRawData; aResults->bits = SAMSUNG_BITS; aResults->decode_type = SAMSUNG; diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index bcb9eb9d2..d97ff575d 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -91,7 +91,7 @@ #define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms struct PulseDistanceWidthProtocolConstants const SonyProtocolConstants PROGMEM = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK, -SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; +SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_WIDTH, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; /************************************ * Start of send and decode functions @@ -122,13 +122,7 @@ bool IRrecv::decodeSony() { return false; } - if (!decodePulseDistanceWidthData_P(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("Sony: ")); - Serial.println(F("Decode failed")); -#endif - return false; - } + decodePulseDistanceWidthData_P(&SonyProtocolConstants, (decodedIRData.rawlen - 1) / 2, 3); // Success // decodedIRData.flags = IRDATA_FLAGS_IS_LSB_FIRST; // Not required, since this is the start value From 1c84ee96680eadc0563659babb913915df477171 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 4 Aug 2025 12:43:05 +0200 Subject: [PATCH 093/133] Changed DECODE_STRICT_CHECKS to USE_STRICT_DECODER and implemented it --- .github/workflows/LibraryBuild.yml | 8 +- README.md | 2 +- examples/UnitTest/UnitTest.ino | 5 +- src/IRReceive.hpp | 594 +++++++++++++++-------------- src/IRremoteInt.h | 18 +- 5 files changed, 319 insertions(+), 308 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index e819d7e3d..eacec58e1 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -85,15 +85,15 @@ jobs: include: - arduino-boards-fqbn: arduino:avr:uno build-properties: # the flags were put in compiler.cpp.extra_flags + ReceiveDemo: -DUSE_STRICT_DECODER -DDEBUG -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK SimpleSender: -DUSE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN - ReceiveDemo: -DIR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK IRremoteExtensionTest: -DRAW_BUFFER_LENGTH=1200 -DIR_SEND_PIN=3 - arduino-boards-fqbn: arduino:avr:uno|DEBUG_TRACE build-properties: # the flags were put in compiler.cpp.extra_flags - UnitTest: -DUSE_THRESHOLD_DECODER - IRremoteExtensionTest: -DIR_SEND_PIN=3 - TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER + 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 diff --git a/README.md b/README.md index 99c4ce465..0ba4defc5 100644 --- a/README.md +++ b/README.md @@ -894,8 +894,8 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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` | 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. | diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index e03e4d1f9..4cb0b6bad 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -46,7 +46,8 @@ //#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 458 bytes program memory. +//#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. @@ -87,9 +88,7 @@ #define DECODE_SONY #define DECODE_SAMSUNG #define DECODE_LG -# if defined(USE_THRESHOLD_DECODER) #define DECODE_LEGO_PF // LEGO is skipped, since it is difficult to receive because of its short marks and spaces -# endif #endif #define DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here. diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index b6cea9e87..afe36d487 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -959,8 +959,8 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy * @return true if decoding successful * */ -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 = &irparams.rawbuf[aStartOffset]; @@ -977,13 +977,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=")); @@ -997,15 +998,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) { @@ -1021,60 +1064,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 < &irparams.rawbuf[irparams.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; @@ -1085,25 +1077,36 @@ bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRa * Decode pulse distance protocols for PulseDistanceWidthProtocolConstants. * @return true if decoding was successful */ -void 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) { +#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 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 { @@ -1111,6 +1114,7 @@ void IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *a } decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros, aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK)); +# endif #endif } @@ -1291,15 +1295,15 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants // Check header "mark" and "space" 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")); + 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")); + Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex)); + Serial.println(F(": Header space length is wrong")); #endif return false; } @@ -1310,15 +1314,15 @@ bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolC // Check header "mark" and "space" if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->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(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { #if defined(LOCAL_TRACE) - Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->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; } @@ -1334,7 +1338,7 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTick if (decodedIRData.initialGapTicks < aMaximumRepeatSpaceTicks #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 */ + && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 44 bytes program space */ #endif ) { decodedIRData.flags |= IRDATA_FLAGS_IS_REPEAT; @@ -1349,24 +1353,24 @@ 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 (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); + 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; } @@ -1379,24 +1383,24 @@ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCo 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); + 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; } @@ -1414,37 +1418,37 @@ bool matchMark(uint16_t aMeasuredTicks, uint16_t 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 + 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; + // 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("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); + 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))); + // 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")); - } + if (passed) { + Serial.println(F(" => passed")); + } else { + Serial.println(F(" => FAILED")); + } # endif - return passed; + return passed; #endif } @@ -1461,36 +1465,36 @@ bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { 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 + 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; + // 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); + 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))); + // 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")); - } + if (passed) { + Serial.println(F(" => passed")); + } else { + Serial.println(F(" => FAILED")); + } # endif - return passed; + return passed; #endif } @@ -1545,63 +1549,63 @@ void IRrecv::printActiveIRProtocols(Print *aSerial) { */ 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 } @@ -1634,11 +1638,11 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) aSerial->print(getProtocolString()); if (decodedIRData.protocol == UNKNOWN) { #if defined(DECODE_HASH) - aSerial->print(F(" Hash=0x")); + aSerial->print(F(" Hash=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 @@ -1649,7 +1653,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) #endif } else { #if defined(DECODE_DISTANCE_WIDTH) - if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) { + if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_WIDTH) { #endif /* * New decoders have address and command @@ -1673,7 +1677,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) aSerial->print(F(", Toggle=1")); } #if defined(DECODE_DISTANCE_WIDTH) - } + } #endif /* @@ -1684,7 +1688,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) #if (__INT_WIDTH__ < 32) aSerial->print(decodedIRData.decodedRawData, HEX); #else - PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); + PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); #endif aSerial->print(F(", ")); @@ -1727,7 +1731,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK); aSerial->println(F("us")); #else - aSerial->println(); + aSerial->println(); #endif } } @@ -1814,11 +1818,11 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { aSerial->print(getProtocolString(aIRDataPtr->protocol)); if (aIRDataPtr->protocol == UNKNOWN) { #if defined(DECODE_HASH) - aSerial->print(F(" Hash=0x")); + aSerial->print(F(" Hash=0x")); #if (__INT_WIDTH__ < 32) - aSerial->print(aIRDataPtr->decodedRawData, HEX); + aSerial->print(aIRDataPtr->decodedRawData, HEX); #else - PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX); + PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX); #endif #endif @@ -1829,7 +1833,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { #endif } else { #if defined(DECODE_DISTANCE_WIDTH) - if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) { + if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) { #endif /* * New decoders have address and command @@ -1853,7 +1857,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { aSerial->print(F(" Toggle=1")); } #if defined(DECODE_DISTANCE_WIDTH) - } + } #endif /* @@ -1864,7 +1868,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { #if (__INT_WIDTH__ < 32) aSerial->print(aIRDataPtr->decodedRawData, HEX); #else - PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX); + PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX); #endif /* * Print number of bits processed @@ -1895,7 +1899,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK); aSerial->println(F("us")); #else - aSerial->println(); + aSerial->println(); #endif } } @@ -1991,48 +1995,48 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(F(" uint32_t tRawData[]={0x")); # else aSerial->print(F("Send on a 32 bit platform with: ")); - tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1; - if(tNumberOfArrayData > 1) { - aSerial->println(); - aSerial->print(F(" uint64_t tRawData[]={0x")); + tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1; + if(tNumberOfArrayData > 1) { + aSerial->println(); + aSerial->print(F(" uint64_t tRawData[]={0x")); # endif - for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) { + for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) { # if (__INT_WIDTH__ < 32) - aSerial->print(decodedIRData.decodedRawDataArray[i], HEX); + aSerial->print(decodedIRData.decodedRawDataArray[i], HEX); # else - PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX); + PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX); # endif - if (i != tNumberOfArrayData - 1) { - aSerial->print(F(", 0x")); + if (i != tNumberOfArrayData - 1) { + aSerial->print(F(", 0x")); + } } + aSerial->println(F("};")); + aSerial->print(F(" ")); } - aSerial->println(F("};")); - aSerial->print(F(" ")); + } else { + aSerial->print(F("Send with: ")); } - } else { - aSerial->print(F("Send with: ")); - } - aSerial->print(F("IrSender.send")); + aSerial->print(F("IrSender.send")); #else aSerial->print(F("Send with: IrSender.send")); #endif #if defined(DECODE_DISTANCE_WIDTH) - if (decodedIRData.protocol != PULSE_DISTANCE && decodedIRData.protocol != PULSE_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 (decodedIRData.protocol == MAGIQUEST) { # 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 - } else { - aSerial->print(decodedIRData.address, HEX); - } + } else { + aSerial->print(decodedIRData.address, HEX); + } #else /* * New decoders have address and command @@ -2050,45 +2054,45 @@ void IRrecv::printIRSendUsage(Print *aSerial) { } #if defined(DECODE_DISTANCE_WIDTH) - } else { - /* - * Pulse distance or pulse width here - */ - aSerial->print(F("PulseDistanceWidth")); - if(tNumberOfArrayData > 1) { - aSerial->print(F("FromArray(38, ")); } else { - aSerial->print(F("(38, ")); - } - printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo); + /* + * Pulse distance or pulse width here + */ + aSerial->print(F("PulseDistanceWidth")); + if(tNumberOfArrayData > 1) { + aSerial->print(F("FromArray(38, ")); + } else { + aSerial->print(F("(38, ")); + } + printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo); - if(tNumberOfArrayData > 1) { - aSerial->print(F(", &tRawData[0], ")); - } else { - aSerial->print(F(", 0x")); + if(tNumberOfArrayData > 1) { + aSerial->print(F(", &tRawData[0], ")); + } else { + 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 - aSerial->print(F(", ")); - } - aSerial->print(decodedIRData.numberOfBits);// aNumberOfBits - aSerial->print(F(", PROTOCOL_IS_")); + aSerial->print(F(", ")); + } + aSerial->print(decodedIRData.numberOfBits); // aNumberOfBits + aSerial->print(F(", PROTOCOL_IS_")); - if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) { - aSerial->print('M'); - } else { - aSerial->print('L'); + if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) { + aSerial->print('M'); + } else { + aSerial->print('L'); + } + aSerial->print(F("SB_FIRST, , ")); } - aSerial->print(F("SB_FIRST, , ")); - } #endif #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6) - if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A)) { - aSerial->print(F(", 0x")); - aSerial->print(decodedIRData.extra, HEX); - } + if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A)) { + aSerial->print(F(", 0x")); + aSerial->print(decodedIRData.extra, HEX); + } #endif aSerial->print(F(");")); aSerial->println(); @@ -2106,11 +2110,11 @@ 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(' '); @@ -2130,7 +2134,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)) { @@ -2186,16 +2190,16 @@ 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; @@ -2371,12 +2375,12 @@ void IRrecv::printIRResultAsCVariables(Print *aSerial) { #if __INT_WIDTH__ < 32 aSerial->print(F("uint32_t rawData = 0x")); #else - aSerial->print(F("uint64_t rawData = 0x")); + aSerial->print(F("uint64_t rawData = 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(); @@ -2389,10 +2393,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 /********************************************************************************************************************** @@ -2426,66 +2430,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/IRremoteInt.h b/src/IRremoteInt.h index f0daeddd9..ea970f40e 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -319,7 +319,12 @@ class IRrecv { /* * The main decoding functions used by the individual decoders */ - void 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); void decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, @@ -338,8 +343,8 @@ class IRrecv { 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); @@ -420,8 +425,11 @@ class IRrecv { uint8_t repeatCount; // Used e.g. for Denon decode for autorepeat decoding. }; -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.")));; +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); From 7f157f240c1b67fcd6f437ee93ef10be27521a8c Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 7 Aug 2025 01:58:16 +0200 Subject: [PATCH 094/133] Added experimental Velux send function. LED feedback is always enabled for sending. It can only be disabled by using the macro NO_LED_SEND_FEEDBACK_CODE. --- README.md | 65 ++++--- changelog.md | 4 + examples/MicroGirs/MicroGirs.ino | 10 +- .../MultipleSendPins/MultipleSendPins.ino | 2 + examples/ReceiveAndSend/ReceiveAndSend.ino | 7 +- .../ReceiveAndSendDistanceWidth.ino | 9 +- .../ReceiveAndSendHob2Hood.ino | 13 +- .../ReceiveOneAndSendMultiple.ino | 8 +- examples/SendAndReceive/SendAndReceive.ino | 10 +- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 10 +- examples/SendDemo/SendDemo.ino | 14 +- .../SendLGAirConditionerDemo.ino | 9 +- examples/SendProntoDemo/SendProntoDemo.ino | 8 +- examples/SendRawDemo/SendRawDemo.ino | 8 +- examples/SimpleSender/SimpleSender.ino | 7 +- examples/UnitTest/UnitTest.ino | 184 ++++++++++-------- examples/UnitTest/UnitTest.log | 19 +- src/IRFeedbackLED.hpp | 106 +++++----- src/IRProtocol.h | 3 +- src/IRProtocol.hpp | 3 +- src/IRReceive.hpp | 28 ++- src/IRSend.hpp | 170 +++++++--------- src/IRremote.hpp | 7 +- src/IRremoteInt.h | 52 ++--- src/TinyIRReceiver.hpp | 7 +- src/TinyIRSender.hpp | 18 +- src/ir_Others.hpp | 73 ++++++- 27 files changed, 490 insertions(+), 364 deletions(-) diff --git a/README.md b/README.md index 0ba4defc5..4eafbfb7b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A library enabling the sending & receiving of infra-red signals.     [![Badge Version](https://img.shields.io/github/v/release/Arduino-IRremote/Arduino-IRremote?include_prereleases&style=for-the-badge&color=33660e&labelColor=428813&logoColor=white&logo=DocuSign)](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest)     -[![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremoteMultipleMultiple/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master) +[![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)     [![Badge LibraryBuild](https://img.shields.io/github/actions/workflow/status/Arduino-IRremote/Arduino-IRremote/LibraryBuild.yml?branch=master&style=for-the-badge&color=551f47&labelColor=752a61)](https://github.com/Arduino-IRremote/Arduino-IRremote/actions)
@@ -34,6 +34,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) - [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) @@ -123,8 +124,14 @@ See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme # 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**. +- 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. + ## New features of version 4.x -- **Since 4.3 `IrSender.begin(DISABLE_LED_FEEDBACK)` will no longer work**, use `IrSender.begin(DISABLE_LED_FEEDBACK, 0)` instead. +- **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. @@ -163,21 +170,19 @@ if you get false error messages regarding begin() during compilation. - **IRreceiver** and **IRsender** object have been added and can be used without defining them, like the well known Arduino **Serial** object. - Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`. -- Since the decoded values are now in `IrReceiver.decodedIRData` and not in `results` any more, remove the line `decode_results results` or similar. - Like for the Serial object, call [`IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK)`](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L106) or `IrReceiver.begin(IR_RECEIVE_PIN, DISABLE_LED_FEEDBACK)` instead of the `IrReceiver.enableIRIn()` or `irrecv.enableIRIn()` in setup().
-For sending, call `IrSender.begin();` 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.irparams.rawbuf` and `IrReceiver.irparams.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 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). +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: @@ -245,7 +250,8 @@ 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 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. +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
@@ -265,9 +271,6 @@ If you **read the first binary sequence backwards** (right to left), you get the `0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`. -### IRremote functions -Use `bitreverseOneByte()` or `bitreverse32Bit()` for reversing. - ### 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). @@ -287,7 +290,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:
@@ -302,10 +305,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. @@ -313,10 +316,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, @@ -404,15 +407,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 | @@ -912,7 +919,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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 500 bytes for sending. | +| `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. | @@ -1089,10 +1096,10 @@ This works on AVR boards like Uno because each call to` tone()` completely initi 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)
-**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#L334),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. @@ -1103,14 +1110,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).
+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**.
diff --git a/changelog.md b/changelog.md index 4e985c7fe..991766c05 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,10 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Added threshold decoding. - Added support for multiple receiver instances. - 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 Velux send function. + # 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. diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index 316983ac8..194728d32 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -82,6 +82,8 @@ #define BAUDRATE 115200 #define NO_DECODER +//#define NO_LED_FEEDBACK_CODE // Saves 346 bytes program memory + #include "IRremote.hpp" #include @@ -307,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/MultipleSendPins/MultipleSendPins.ino b/examples/MultipleSendPins/MultipleSendPins.ino index 33566bcbc..30a627ef7 100644 --- a/examples/MultipleSendPins/MultipleSendPins.ino +++ b/examples/MultipleSendPins/MultipleSendPins.ino @@ -16,7 +16,9 @@ #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 diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index f156aa6f6..a104f9106 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -84,6 +84,7 @@ //#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 135. @@ -129,7 +130,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 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.")); diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 31391cb57..dac652bb4 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -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. @@ -101,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/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index f9b3a2b09..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 @@ -86,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/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index fd2a89326..3eb22c933 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -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() @@ -125,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))); } diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 441277a9c..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. @@ -67,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 diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index 5046b96cf..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 @@ -119,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/SendDemo.ino b/examples/SendDemo/SendDemo.ino index bafc8852c..f1b8e95ac 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -44,8 +44,9 @@ //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition //#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal. +//#define NO_LED_FEEDBACK_CODE // Saves 322 bytes program memory #if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85 -#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory +#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 @@ -76,8 +77,11 @@ 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 -// 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 @@ -86,7 +90,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 ")); @@ -107,7 +111,7 @@ void setup() { Serial.println(F(" us")); #endif -#if defined(LED_BUILTIN) && !defined(NO_LED_FEEDBACK_CODE) +#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 diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index a92e45e21..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. @@ -78,9 +82,10 @@ void setup() { 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/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index e935d00c1..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 @@ -69,7 +71,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 + */ } void loop() { diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 5b03a6438..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. @@ -61,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/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index c6d97d62d..91797630e 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -19,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 @@ -37,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/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 4cb0b6bad..9faa6bf57 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -53,9 +53,10 @@ //#define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition //#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal. -#if FLASHEND <= 0x7FFF // For 32k flash or less, like ATmega328 -#define NO_LED_FEEDBACK_CODE // Saves 344 bytes program memory -#endif +#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 // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, @@ -183,7 +184,11 @@ void setup() { 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 @@ -192,7 +197,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 ")); @@ -422,6 +427,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() { @@ -433,28 +443,27 @@ void loop() { Serial.print(sAddress, HEX); Serial.print(F(" command=0x")); Serial.print(sCommand, HEX); - if(sRepeats > 0) { - Serial.print(F(" ")); - Serial.print(sRepeats, HEX); - Serial.print(F(" repeats")); + 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); - /* - * Complete NEC frames as repeats to force decoding as NEC2 are tested here - */ for (int8_t i = 0; i < sRepeats; i++) { # if defined(DEBUG_BUTTON_PIN) if (digitalRead(DEBUG_BUTTON_PIN) != LOW) { @@ -462,7 +471,7 @@ void loop() { delayMicroseconds(NEC_REPEAT_DISTANCE - 20000); // 20000 is just a guess } # endif - IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); + IrSender.sendNEC(sAddress & 0xFF, sCommand, 0); // sending repeat frames -> decodes as NEC2 checkReceive(sAddress & 0xFF, sCommand); } @@ -470,24 +479,25 @@ 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 (sAddress == 0xFFF1) { -# 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 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]; -# if defined(DECODE_NEC) +# if defined(DECODE_NEC) /* * Send constant values only once in this demo */ @@ -537,18 +547,18 @@ void loop() { IrSender.sendNECMSB(0x40802CD3, 32, false); checkReceive(0x0102, 0x34); delay(DELAY_AFTER_SEND); -# endif // defined(DECODE_NEC) +# endif // defined(DECODE_NEC) -# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceivedRawData(0xA010B02002); -# endif +# endif delay(DELAY_AFTER_SEND); /* @@ -557,60 +567,60 @@ void loop() { 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 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0xA010B02002); -# endif +# 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 +# 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); checkReceive(0x0B, 0x10); -# else +# else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0x40040D000805, 48, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0x40040D000805); -# endif +# endif delay(DELAY_AFTER_SEND); -# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) -# if defined(DECODE_DISTANCE_WIDTH) -# if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) +# 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 1=550|1700, 0=550|600")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# 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); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 8900, 4450, 550, 1700, 550, 600, 0x43D8613CBC3B, 52, PROTOCOL_IS_MSB_FIRST, 0, NO_REPEATS); checkReceivedRawData(0x43D8613CBC3B); -# endif +# endif delay(DELAY_AFTER_SEND); 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 +# if __INT_WIDTH__ < 32 IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[0], 52, PROTOCOL_IS_MSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, 0x123456789ABC, 52, PROTOCOL_IS_MSB_FIRST, 0, 0); checkReceivedRawData(0x123456789ABC); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 32 bit PulseWidth 0x43D8613C MSB first 1=600|300, 0=300|300")); Serial.flush(); @@ -619,50 +629,50 @@ void loop() { checkReceivedRawData(0x43D8613C); delay(DELAY_AFTER_SEND); -# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) +# else // defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) 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); checkReceivedArray(tRawData, 3); -# else +# 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); checkReceivedArray(tRawData, 2); -# endif +# endif delay(DELAY_AFTER_SEND); 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 +# if __INT_WIDTH__ < 32 tRawData[1] = 0xDCBA9; IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 300, 600, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 300, 600, 600, 300, 0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0xDCBA987654321); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println( F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600")); Serial.flush(); -# if __INT_WIDTH__ < 32 +# if __INT_WIDTH__ < 32 tRawData[2] = ~tRawData[0]; tRawData[3] = ~tRawData[1]; IrSender.sendPulseDistanceWidthFromArray(38, 300, 600, 600, 300, 300, 600, &tRawData[2], 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedArray(tRawData, 2); -# else +# else IrSender.sendPulseDistanceWidth(38, 300, 600, 600, 300, 300, 600, ~0xDCBA987654321, 52, PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceivedRawData(0xDCBA987654321); -# endif +# endif delay(DELAY_AFTER_SEND); Serial.println(F("Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500")); @@ -672,24 +682,31 @@ void loop() { checkReceivedRawData(sCommand); delay(DELAY_AFTER_SEND); -# if defined(DECODE_SONY) +# if defined(DECODE_SONY) + Serial.println(F("Send Velux 0x765432 decoded as PulseDistanceWidth 0x44D5E6 LSB first 1=1275|475, 0=475|1275")); + Serial.flush(); + IrSender.sendPulseDistanceWidth_P(&VeluxProtocolConstants, 0x765432, VELUX_BITS, 0); + // We send without header, so >> 1. We send as pulse width so we must invert result, which is decoded as pulse distance + checkReceivedRawData((~(0x765432 >> 1)) & 0x7FFFFF); // ~0x3B2A19 = FFC4D5E6 & 0x7FFFFF = 0x44D5E6 + delay(DELAY_AFTER_SEND); +# endif + +# 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 +# endif 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) -# endif // if FLASHEND >= 0x7FFF ... +# 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 1=576|576, 0=287|864")); @@ -707,30 +724,29 @@ void loop() { 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) - - } -#endif // if FLASHEND >= 0x3FFF + } // end of once at first loop +#endif // if FLASHEND >= 0x7FFF #if defined(DECODE_NEC) Serial.println(F("Send Onkyo (NEC with 16 bit command)")); Serial.flush(); - IrSender.sendOnkyo(sAddress, (sCommand + 1) << 8 | sCommand, 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 @@ -738,19 +754,19 @@ void loop() { #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 @@ -772,19 +788,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 @@ -792,19 +808,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 @@ -812,13 +828,13 @@ 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 @@ -828,13 +844,13 @@ void loop() { Serial.flush(); sLastSendToggleValue = sAddress & 0x01; // to modify toggling at each loop - IrSender.sendRC6(sAddress & 0xFF, sCommand, 0, true); + 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, 0, 0x2711, true); + IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true); checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); #endif @@ -860,7 +876,7 @@ void loop() { #if defined(DECODE_BEO) 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")); @@ -909,7 +925,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 @@ -932,7 +948,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 @@ -942,7 +958,7 @@ 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 diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index df0e73796..68e99aee2 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -295,6 +295,21 @@ rawData[18]: Duration=20950us +Send Velux 0x765432 decoded as PulseDistanceWidth 0x44D5E6 LSB first 1=1275|475, 0=475|1275 +Protocol=PulseDistance, Raw-Data=0x44D5E6, 23 bits, LSB first, Gap=746700us, Duration=42700us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 600, 1200, 550, 1200, 1300, 400, 0x44D5E6, 23, PROTOCOL_IS_LSB_FIRST, , ); +rawData[50]: + -746700 + + 600,-1200 + +1300,- 450 + 500,-1200 + 550,-1200 +1350,- 350 + +1300,- 400 + 550,-1200 + 550,-1150 + 600,-1150 + + 550,-1200 +1300,- 400 + 550,-1150 +1300,- 400 + + 550,-1200 +1350,- 350 + 550,-1150 + 550,-1200 + +1300,- 400 +1300,- 400 + 600,-1150 +1350,- 350 + +1300,- 400 +1350,- 400 + 500,-1200 +1350 +Duration=42700us + + 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); @@ -813,7 +828,7 @@ 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, Gap=923450us, Duration=67850us @@ -1354,7 +1369,7 @@ ERROR: Unknown protocol Stop receiver Start receiver -address=0x1F3 command=0x98 +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 diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 0db0c02f8..a40abdad6 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -40,104 +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 /** - * Enables 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) { - // Turn user defined pin LED on -#if defined(FEEDBACK_LED_IS_ACTIVE_LOW) - if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);} -#else - if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);} -#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 # else digitalWriteFast(LED_BUILTIN, HIGH); // For AVR, this generates a single sbi command # endif #endif - } - } else { - if (FeedbackLEDControl.FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN) { - // Turn user defined pin LED off + + } else { #if defined(FEEDBACK_LED_IS_ACTIVE_LOW) - if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, HIGH);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, HIGH);} + if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { + digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW); + } else { + digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW); + } #else - if (__builtin_constant_p(FeedbackLEDControl.FeedbackLEDPin) ) { digitalWriteFast(FeedbackLEDControl.FeedbackLEDPin, LOW);} else { digitalWrite(FeedbackLEDControl.FeedbackLEDPin, LOW);} + 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 # else 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 } } @@ -147,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 c556c4df2..258aaf5b2 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -122,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 diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 591c21f2d..aa058fa28 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -74,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!!! @@ -84,7 +85,7 @@ PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Appl 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 }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index afe36d487..ba4780667 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -50,6 +50,11 @@ //#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 * @{ */ @@ -70,16 +75,10 @@ unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR wi */ IRrecv::IRrecv() { setReceivePin(0); -#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) - setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); -#endif } IRrecv::IRrecv(uint_fast8_t aReceivePin) { setReceivePin(aReceivePin); -#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) - setLEDFeedback(0, DO_NOT_ENABLE_LED_FEEDBACK); -#endif } /** @@ -89,8 +88,8 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin) { */ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { setReceivePin(aReceivePin); -#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) - setLEDFeedback(aFeedbackLEDPin, DO_NOT_ENABLE_LED_FEEDBACK); +#if defined(LED_RECEIVE_FEEDBACK_CODE) + setLEDFeedbackPin(aFeedbackLEDPin); #else (void) aFeedbackLEDPin; #endif @@ -264,8 +263,8 @@ void IRrecv::ReceiveInterruptHandler() { } } -#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) - if (FeedbackLEDControl.LedFeedbackEnabled & LED_FEEDBACK_ENABLED_FOR_RECEIVE) { +#if defined(LED_RECEIVE_FEEDBACK_CODE) + if (FeedbackLEDControl.LedFeedbackEnabled) { setFeedbackLED(tIRInputLevel == INPUT_MARK); } #endif @@ -317,12 +316,9 @@ ISR() void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) { setReceivePin(aReceivePin); -#if !defined(NO_LED_RECEIVE_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; diff --git a/src/IRSend.hpp b/src/IRSend.hpp index a47055703..36792eff8 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -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_SEND_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_SEND_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_SEND_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_SEND_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_SEND_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_SEND_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. @@ -1170,10 +1153,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_SEND_FEEDBACK_CODE) - if (FeedbackLEDControl.LedFeedbackEnabled == LED_FEEDBACK_ENABLED_FOR_SEND) { - setFeedbackLED(true); - } +# if defined(LED_SEND_FEEDBACK_CODE) + setFeedbackLED(true); # endif #endif @@ -1201,29 +1182,29 @@ void IRsend::mark(uint16_t aMarkMicros) { customDelayMicroseconds(aMarkMicros); IRLedOff(); -# if !defined(NO_LED_SEND_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_SEND_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 - IR LED is active - */ + ****************************************/ noInterrupts(); // do not let interrupts extend the short on period # 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) @@ -1245,11 +1226,15 @@ void IRsend::mark(uint16_t aMarkMicros) { 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 - IR LED is inactive + * 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. */ + 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)) { @@ -1274,28 +1259,26 @@ void IRsend::mark(uint16_t aMarkMicros) { */ interrupts(); -# if !defined(NO_LED_SEND_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_SEND_FEEDBACK_CODE enabled - * and 8.1 us with NO_LED_SEND_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 @@ -1303,44 +1286,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_SEND_FEEDBACK_CODE enabled - * and 3 us with NO_LED_SEND_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_SEND_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_SEND_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 } @@ -1382,16 +1351,15 @@ void IRsend::IRLedOff() { # endif #endif -#if !defined(NO_LED_SEND_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); diff --git a/src/IRremote.hpp b/src/IRremote.hpp index fac095a63..b84963e6f 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -212,6 +212,7 @@ #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 @@ -219,6 +220,9 @@ #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" /* @@ -232,7 +236,8 @@ #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 diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index ea970f40e..745a1558a 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -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. @@ -159,11 +152,11 @@ struct IRData { 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. + 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 send function. + 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 @@ -174,8 +167,8 @@ struct IRData { * 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. + 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. }; /* @@ -229,6 +222,7 @@ struct decode_results { /** * Main class for receiving IR signals */ +#define USE_DEFAULT_FEEDBACK_LED_PIN 0 // we need it here class IRrecv { public: @@ -457,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(); @@ -530,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); @@ -732,7 +717,10 @@ class IRsend { 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, uint8_t aCRC, + 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/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 7b61f205f..cd5fe88e8 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -131,6 +131,9 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; # endif #endif +#if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) +#define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative +#endif #if !( \ (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \ @@ -171,7 +174,7 @@ void IRPinChangeInterruptHandler(void) { */ uint_fast8_t tIRLevel = digitalReadFast(IR_RECEIVE_PIN); -#if !defined(NO_LED_RECEIVE_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 @@ -463,7 +466,7 @@ bool isIRReceiverAttachedForTinyReceiver() { bool initPCIInterruptForTinyReceiver() { pinModeFast(IR_RECEIVE_PIN, INPUT); -#if !defined(NO_LED_RECEIVE_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); diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index be0d07ef7..1053d52c7 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -66,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 */ @@ -164,7 +168,7 @@ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast } } } -#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -187,7 +191,7 @@ 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(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -250,7 +254,7 @@ void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_ } } } -#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -270,7 +274,7 @@ 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(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -324,7 +328,7 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin } } } -#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -347,7 +351,7 @@ 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(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); @@ -399,7 +403,7 @@ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats } } } -#if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) +#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); diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index 6db70fc32..6d893cd85 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -58,8 +58,8 @@ #define DISH_ZERO_SPACE 2800 #define DISH_REPEAT_SPACE 6200 // really? -struct PulseDistanceWidthProtocolConstants const DishProtocolConstants PROGMEM = { UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, -DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 40, nullptr }; +struct PulseDistanceWidthProtocolConstants const DishProtocolConstants PROGMEM = {UNKNOWN, 56, DISH_HEADER_MARK, DISH_HEADER_SPACE, + DISH_BIT_MARK, DISH_ONE_SPACE, DISH_BIT_MARK, DISH_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 40, nullptr}; void IRsend::sendDish(uint16_t aData) { sendPulseDistanceWidth_P(&DishProtocolConstants, aData, DISH_BITS, 4); @@ -84,11 +84,11 @@ void IRsend::sendDish(uint16_t aData) { #define WHYNTER_ONE_SPACE 2150 #define WHYNTER_ZERO_SPACE 750 -struct PulseDistanceWidthProtocolConstants const WhynterProtocolConstants PROGMEM = { WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, -WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 110, nullptr }; +struct PulseDistanceWidthProtocolConstants const WhynterProtocolConstants PROGMEM = {WHYNTER, 38, WHYNTER_HEADER_MARK, WHYNTER_HEADER_SPACE, + WHYNTER_BIT_MARK, WHYNTER_ONE_SPACE, WHYNTER_BIT_MARK, WHYNTER_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, 110, nullptr}; -void IRsend::sendWhynter(uint32_t aData, uint8_t aNumberOfBitsToSend) { - sendPulseDistanceWidth_P(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfBitsToSend); +void IRsend::sendWhynter(uint32_t aData, int_fast8_t aNumberOfRepeats) { + sendPulseDistanceWidth_P(&WhynterProtocolConstants, aData, NEC_BITS, aNumberOfRepeats); } bool IRrecv::decodeWhynter() { @@ -107,5 +107,66 @@ bool IRrecv::decodeWhynter() { return true; } +/** + * VELUX + * see https://github.com/XPModder/Velux-IR-protocol + * see https://github.com/Arduino-IRremote/Arduino-IRremote/issues/612 + * We have a pulse width protocol with constant bit length of 1700 us with no header and one autorepeat after 27 ms. + * Length of one frame is constant 23 * 1700 + 425 (for stop bit) = 39525 = 40 ms + * + * BIT meaning: + * Bit 0 is stop + * Bit 1 is up | 0 or down | 1 + * Bit 2 is automatic and also set for stop + * Bit 3 is Motor 3 + * Bit 4 is Motor 2 + * Bit 5 is Motor 1 + * [6:9] is motor set (from 1 to 10), 0 = all sets + * [10:19] security code + * [20:23] is checksum, no clue how to compute it. It is no simple XOR or addition + * Here some checksum raw data to verify a checksum function: + * 0x424 -> 1 + * 0x426 -> B + * 0x425 -> 4 + * 0x414 -> B + * 0x415 -> E + * 0x7626 -> 3 + * 0x7624 -> 9 + * 0x7614 -> 3 + * 0x760C -> 6 + * 0x760A -> 1 + */ + +// All timings are in microseconds +#define VELUX_BITS 24 // We have pulse width, so we have no stop bit +#define VELUX_HEADER_MARK 0 +#define VELUX_HEADER_SPACE 0 +#define VELUX_UNIT 425 +#define VELUX_ONE_MARK (3*VELUX_UNIT) // 1275 +#define VELUX_ONE_SPACE VELUX_UNIT +#define VELUX_ZERO_MARK VELUX_UNIT +#define VELUX_ZERO_SPACE (3*VELUX_UNIT) +#define VELUX_PERIOD ((23 * 4) + 1 ) * VELUX_UNIT) // 39525 +#define VELUX_AUTOREPEAT_SPACE 27000 // 27ms +#define VELUX_REPEAT_SPACE 100000 // 100ms, which is just a guess + +struct PulseDistanceWidthProtocolConstants const VeluxProtocolConstants PROGMEM = {OTHER, 30, VELUX_HEADER_MARK, VELUX_HEADER_SPACE, + VELUX_ONE_MARK, VELUX_ONE_SPACE, VELUX_ZERO_MARK, VELUX_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_WIDTH, 27, nullptr}; + +void IRsend::sendVelux(uint8_t aCommand, uint8_t aMotorNumber, uint8_t aMotorSet, uint16_t aSecurityCode, uint8_t aCRC, + int_fast8_t aNumberOfRepeats) { + + sendVelux(((uint32_t)aCRC << 20) | ((uint32_t)aSecurityCode << 10) | (aMotorSet << 6) | (aMotorNumber << 3) | aCommand, aNumberOfRepeats); +} + +void IRsend::sendVelux(uint32_t aData, int_fast8_t aNumberOfRepeats) { + do { + sendPulseDistanceWidth_P(&VeluxProtocolConstants, aData, VELUX_BITS, 0); + delay(VELUX_AUTOREPEAT_SPACE / MICROS_IN_ONE_MILLI); + sendPulseDistanceWidth_P(&VeluxProtocolConstants, aData, VELUX_BITS, 0); + delay(VELUX_REPEAT_SPACE / MICROS_IN_ONE_MILLI); + aNumberOfRepeats--; + } while (aNumberOfRepeats >= 0); +} /** @}*/ #endif // _IR_OTHERS_HPP From 8b0b70db4cf02a2058f62eae12499fa480cdb909 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sat, 9 Aug 2025 15:47:41 +0200 Subject: [PATCH 095/133] Bumped version to 4.5.0 --- README.md | 6 ++++-- changelog.md | 3 ++- examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp | 2 +- library.json | 2 +- library.properties | 4 ++-- src/IRVersion.h | 6 +++--- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4eafbfb7b..e3661e521 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr ` 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): @@ -125,7 +125,9 @@ See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme 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**. +- 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. diff --git a/changelog.md b/changelog.md index 991766c05..65118f7ed 100644 --- a/changelog.md +++ b/changelog.md @@ -2,12 +2,13 @@ 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. -- Added support for multiple receiver instances. - 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). diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 8121e115f..9f1a73401 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -39,7 +39,7 @@ // 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 diff --git a/library.json b/library.json index 62260bdf3..7aecaa48c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.4.3", + "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", diff --git a/library.properties b/library.properties index b5c0b1eb2..ec368ba68 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.4.3 +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. +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/src/IRVersion.h b/src/IRVersion.h index acbafa22c..24890fc3f 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.4.2" +#define VERSION_IRREMOTE "4.5.0" #define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 4 -#define VERSION_IRREMOTE_PATCH 2 +#define VERSION_IRREMOTE_MINOR 5 +#define VERSION_IRREMOTE_PATCH 0 /* * Macro to convert 3 version parts into an integer From 508cbf92b18203a30eb2f5f47702b9e0a7008c4b Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 14 Aug 2025 02:11:02 +0200 Subject: [PATCH 096/133] Added Velux checksum computation --- README.md | 59 ++++++++++--------- examples/UnitTest/UnitTest.ino | 25 +++++--- examples/UnitTest/UnitTest.log | 24 ++++---- src/IRSend.hpp | 4 +- src/IRremoteInt.h | 3 +- src/ir_Others.hpp | 101 +++++++++++++++++++++++++-------- 6 files changed, 140 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index e3661e521..d2d888c21 100644 --- a/README.md +++ b/README.md @@ -777,93 +777,92 @@ The examples are available at File > Examples > Examples from Custom Libraries / **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**. +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 +#### [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. -#### MultipleSendPins +#### [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 +#### [SendAndReceive](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino) Demonstrates **receiving while sending**. -#### ReceiveAndSend +#### [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. ![LG AKB73315611 remote](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/LG_AKB73315611.jpg)
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). ![Delay](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/IR_UnitTest_delay.bmp) diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 9faa6bf57..4a28f40ea 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -682,20 +682,31 @@ void loop() { checkReceivedRawData(sCommand); delay(DELAY_AFTER_SEND); -# if defined(DECODE_SONY) - Serial.println(F("Send Velux 0x765432 decoded as PulseDistanceWidth 0x44D5E6 LSB first 1=1275|475, 0=475|1275")); + Serial.println(F("Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275")); Serial.flush(); - IrSender.sendPulseDistanceWidth_P(&VeluxProtocolConstants, 0x765432, VELUX_BITS, 0); - // We send without header, so >> 1. We send as pulse width so we must invert result, which is decoded as pulse distance - checkReceivedRawData((~(0x765432 >> 1)) & 0x7FFFFF); // ~0x3B2A19 = FFC4D5E6 & 0x7FFFFF = 0x44D5E6 + 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); -# endif # if defined(DECODE_SONY) Serial.println(F("Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600")); Serial.flush(); IrSender.sendPulseDistanceWidth(38, 2400, 600, 1200, 600, 600, 600, (sAddress << 7 | (sCommand & 0x7F)), SIRCS_12_PROTOCOL, - PROTOCOL_IS_LSB_FIRST, 0, 0); + PROTOCOL_IS_LSB_FIRST, 0, 0); checkReceive(sAddress & 0x1F, sCommand & 0x7F); delay(DELAY_AFTER_SEND); # endif diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 68e99aee2..8412904aa 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -295,19 +295,19 @@ rawData[18]: Duration=20950us -Send Velux 0x765432 decoded as PulseDistanceWidth 0x44D5E6 LSB first 1=1275|475, 0=475|1275 -Protocol=PulseDistance, Raw-Data=0x44D5E6, 23 bits, LSB first, Gap=746700us, Duration=42700us -Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 600, 1200, 550, 1200, 1300, 400, 0x44D5E6, 23, PROTOCOL_IS_LSB_FIRST, , ); +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]: - -746700 - + 600,-1200 - +1300,- 450 + 500,-1200 + 550,-1200 +1350,- 350 - +1300,- 400 + 550,-1200 + 550,-1150 + 600,-1150 - + 550,-1200 +1300,- 400 + 550,-1150 +1300,- 400 - + 550,-1200 +1350,- 350 + 550,-1150 + 550,-1200 - +1300,- 400 +1300,- 400 + 600,-1150 +1350,- 350 - +1300,- 400 +1350,- 400 + 500,-1200 +1350 -Duration=42700us + -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 1=1200|300, 0=600|600 diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 36792eff8..7a349aa3e 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -1081,7 +1081,9 @@ void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const } /** - * Sends Biphase data MSB first + * 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. * Always send start bit, do not send the trailing space of the start bit * 0 -> mark+space * 1 -> space+mark diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 745a1558a..3b01e96ff 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -718,8 +718,7 @@ class IRsend { __attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats)."))); void sendWhynter(uint32_t aData, int_fast8_t aNumberOfRepeats); - void sendVelux(uint8_t aCommand, uint8_t aMotorNumber, uint8_t aMotorSet, uint16_t aSecurityCode, uint8_t aCRC, - 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) diff --git a/src/ir_Others.hpp b/src/ir_Others.hpp index 6d893cd85..39b04e4ee 100644 --- a/src/ir_Others.hpp +++ b/src/ir_Others.hpp @@ -114,27 +114,42 @@ bool IRrecv::decodeWhynter() { * We have a pulse width protocol with constant bit length of 1700 us with no header and one autorepeat after 27 ms. * Length of one frame is constant 23 * 1700 + 425 (for stop bit) = 39525 = 40 ms * - * BIT meaning: - * Bit 0 is stop - * Bit 1 is up | 0 or down | 1 - * Bit 2 is automatic and also set for stop - * Bit 3 is Motor 3 - * Bit 4 is Motor 2 - * Bit 5 is Motor 1 - * [6:9] is motor set (from 1 to 10), 0 = all sets - * [10:19] security code - * [20:23] is checksum, no clue how to compute it. It is no simple XOR or addition - * Here some checksum raw data to verify a checksum function: - * 0x424 -> 1 - * 0x426 -> B - * 0x425 -> 4 - * 0x414 -> B - * 0x415 -> E - * 0x7626 -> 3 - * 0x7624 -> 9 - * 0x7614 -> 3 - * 0x760C -> 6 - * 0x760A -> 1 + * BIT meaning for MSB first: + * Bit 23 is stop + * Bit 22 is up = 0 or down = 1, 0 for stop + * Bit 21 is automatic and also set for stop + * Bit 20 is Motor 3 + * Bit 19 is Motor 2 + * Bit 18 is Motor 1 + * [14:17] is 4 bit motor set (from 1 to 10), 0 = all sets + * [4:13] 10 bit security code + * [1:3] is checksum + * + * Checksum is independent of the 10 bit security code + * + * !!! MOTOR 3 is coded with 0x04, since motor numbers are bit position coded to enable 0x07 as all motors!!! + * Automatic bit is set for all following codes! + * Checksum for UP (0x1): + * All (Motor = 0x7, set = 0) -> 2 == Motor 1 set A or Motor 3 set 5 + * Table of checksum (x) for motor / set combinations + * Set 1 2 3 4 5 6 7 8 9 A + * Motor 1 9 A B C D E F 0 1 2 3 4 5 6 | x XOR set = 8 or set XOR 8 = checksum + * Motor 2 C F E 9 8 B A 5 4 7 6 1 0 2 | x XOR set = D = 8 XOR 5 or set XOR 8 XOR 5 = checksum + * Motor 3/4 6 5 4 3 2 1 0 F E D C B A 9 | x XOR set = 7 = 8 XOR F or set XOR 8 XOR F = checksum + * Checksum for DOWN (0x3): + * All -> 7 == Motor 1 set A + * Table of checksum (x) for motor / set combinations + * Set 1 2 3 4 5 6 7 8 9 A + * Motor 1 C F E 9 8 B A 5 4 7 6 1 0 2 | x XOR set = D + * Motor 2 9 A B C D E F 0 1 2 3 4 5 6 | x XOR set = 8 = D XOR 5 + * Motor 3/4 3 0 1 6 7 4 5 A B 8 9 E F D | x XOR set = 2 = D XOR F + * Checksum for STOP (0x5): + * All -> 8 == Motor 1 set A + * Table of checksum (x) for motor / set combinations + * Set 1 2 3 4 5 6 7 8 9 A + * Motor 1 3 0 1 6 7 4 5 A B 8 9 E F D | x XOR set = 2 + * Motor 2 6 5 4 3 2 1 0 F E D C B A 9 | x XOR set = 7 = 2 XOR 5 + * Motor 3/4 C F E 9 8 B A 5 4 7 6 1 0 2 | x XOR set = D = 2 XOR F */ // All timings are in microseconds @@ -150,13 +165,51 @@ bool IRrecv::decodeWhynter() { #define VELUX_AUTOREPEAT_SPACE 27000 // 27ms #define VELUX_REPEAT_SPACE 100000 // 100ms, which is just a guess +#define VELUX_COMMAND_AUTO_UP 0x1 +#define VELUX_COMMAND_AUTO_DOWN 0x3 +#define VELUX_COMMAND_STOP 0x5 + struct PulseDistanceWidthProtocolConstants const VeluxProtocolConstants PROGMEM = {OTHER, 30, VELUX_HEADER_MARK, VELUX_HEADER_SPACE, - VELUX_ONE_MARK, VELUX_ONE_SPACE, VELUX_ZERO_MARK, VELUX_ZERO_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_WIDTH, 27, nullptr}; + VELUX_ONE_MARK, VELUX_ONE_SPACE, VELUX_ZERO_MARK, VELUX_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_WIDTH, 27, nullptr}; -void IRsend::sendVelux(uint8_t aCommand, uint8_t aMotorNumber, uint8_t aMotorSet, uint16_t aSecurityCode, uint8_t aCRC, +/* + * @param aCommand VELUX_COMMAND_AUTO_UP or VELUX_COMMAND_AUTO_DOWN or VELUX_COMMAND_STOP + * @param aMotorNumber 1, 2, 4 = Motor3, 7 = All + * @param aMotorSet 0 = All, 1 to 10 + * !!!NO parameter range check here!!! + */ +void IRsend::sendVelux(uint8_t aCommand, uint8_t aMotorNumber, uint8_t aMotorSet, uint16_t aSecurityCode, int_fast8_t aNumberOfRepeats) { + // Just in case... + if (aMotorNumber == 3) { + aMotorNumber = 4; // motor numbers are bit position coded + } + + /* + * Compute checksum (only for automatic bit set to 1) + */ + uint8_t tChecksum = 8; // Start checksum for command + if (aCommand == VELUX_COMMAND_AUTO_DOWN) { + tChecksum = 0xD; + } + if (aCommand == VELUX_COMMAND_STOP) { + tChecksum = 2; + } + + uint8_t tXORForMotor = 0; + if (aMotorNumber == 2) { + tXORForMotor = 5; + } + if (aMotorNumber == 4) { + tXORForMotor = 0xF; + } + + tChecksum ^= aMotorSet; + tChecksum ^= tXORForMotor; - sendVelux(((uint32_t)aCRC << 20) | ((uint32_t)aSecurityCode << 10) | (aMotorSet << 6) | (aMotorNumber << 3) | aCommand, aNumberOfRepeats); + sendVelux( + ((uint32_t) aCommand << 21) | ((uint32_t) aMotorNumber << 18) | (aMotorSet << 14) | ((uint32_t) aSecurityCode << 4) + | tChecksum, aNumberOfRepeats); } void IRsend::sendVelux(uint32_t aData, int_fast8_t aNumberOfRepeats) { From c2a94307889d5eacfb24e9ce7a79e30dfb97733e Mon Sep 17 00:00:00 2001 From: arjung467 Date: Sun, 24 Aug 2025 21:00:49 +0200 Subject: [PATCH 097/133] Marantz-RC5 extension support (#1314) * Marantz-RC5 extension support Added support for Marantz extension of RC5 protocol. Marantz uses standard RC5x (13 bit) as well as an own version that adds a pause (4x 889 us) after the address and add adds another word (the "extension") to the signal so the the extended message is 19 bit long. * Send function for Marantz variant of RC5x Added support for Marantz variant of RC5 protocol (sending only). Marantz uses standard RC5x (13 bit) as well as an own version that adds a pause (4x 889 us) after the address and add adds another word (the "command extension") to the signal so the extended message is 19 bit long. --------- Co-authored-by: ArminJo --- README.md | 3 +- examples/SendDemo/SendDemo.ino | 14 +++++++- src/IRSend.hpp | 31 ++++++++++++++---- src/IRremoteInt.h | 4 ++- src/ir_RC5_RC6.hpp | 60 ++++++++++++++++++++++++++++++++-- 5 files changed, 100 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d2d888c21..03f1dbb31 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ 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` @@ -131,6 +131,7 @@ Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.ra - 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. diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index f1b8e95ac..f9e41d1fc 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -125,10 +125,12 @@ void setup() { * 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; @@ -344,6 +346,16 @@ void loop() { IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats); delay(DELAY_AFTER_SEND); + Serial.println(F("Send Marantz variant of RC5x with 6 command bits and additiaonal 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 additiaonal command extension")); + Serial.flush(); + IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sCommandExtension, sRepeats); + delay(DELAY_AFTER_SEND); + Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits")); Serial.flush(); IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats); diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 7a349aa3e..ccb5fd4bb 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -115,6 +115,7 @@ 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, uint_fast8_t aFeedbackLEDPin) { @@ -1084,15 +1085,16 @@ void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const * 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. - * Always send start bit, do not send the trailing space of the start bit + * Send an additional start bit if specified, do not send the trailing space of the start bit * 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 + * can only send 31 bit data, since we may 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); @@ -1101,12 +1103,25 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas Serial.print('S'); #endif + uint32_t tMask; + uint_fast8_t tLastBitValue; + bool tNextBitIsOne; +// total number of bits to send including start bit if specified + uint8_t aBitsToSend = aNumberOfBits + (aSendStartBit ? 1 : 0); // Data - Biphase code MSB first + if (aSendStartBit) { // 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--) { + tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit + tLastBitValue = 1; // Start bit is a 1 + tNextBitIsOne = 1; // Start bit is a 1 + } 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 << (aNumberOfBits - 1); // mask is now set for the MSB of data + tLastBitValue = ((aData & tMask) != 0) ? 1 : 0; // remember the value of the first bit to be sent + tNextBitIsOne = tLastBitValue; + } +// now send all bits + for (uint_fast8_t i = aBitsToSend; i > 0; i--) { bool tCurrentBitIsOne = tNextBitIsOne; tMask >>= 1; tNextBitIsOne = ((aData & tMask) != 0) || (i == 1); // true for last bit to avoid extension of mark @@ -1116,6 +1131,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas #endif space(aBiphaseTimeUnit); if (tNextBitIsOne) { + // if next bit is 1 send a single mark mark(aBiphaseTimeUnit); } else { // if next bit is 0, extend the current mark in order to generate a continuous signal without short breaks @@ -1128,6 +1144,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas Serial.print('0'); #endif if (!tLastBitValue) { + // if last bit was 0 send a space mark(aBiphaseTimeUnit); } space(aBiphaseTimeUnit); diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 3b01e96ff..f858b3267 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -589,7 +589,7 @@ class IRsend { __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); @@ -645,6 +645,8 @@ 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); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 3a826f7c9..c5eb1db65 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -81,6 +81,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 // #define RC5_ADDRESS_BITS 5 #define RC5_COMMAND_BITS 6 +#define RC5_EXTENSION_BITS 6 #define RC5_COMMAND_FIELD_BIT 1 #define RC5_TOGGLE_BIT 1 @@ -99,15 +100,70 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 * Start of send and decode functions ************************************/ +/** + * @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X. + * @param aMarantzExtension 6 bit command extension which is sent after aCommand. aCommand and aMarantzExtension are sent after a short pause. + * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. + */ +void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats, + bool aEnableAutomaticToggle) { + + // Set IR carrier frequency + enableIROut (RC5_RC6_KHZ); + + uint16_t tIRData = (aAddress & 0x1F); + + if (aCommand < 0x40) { + // Auto discovery of RC5X, set field bit to 1 + tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); + } else { + // Mask bit 7 of command and let field bit 0 + aCommand &= 0x3F; + } + // Set the command to the 2nd partof data to be sent after the pause + uint16_t tIRExtData = (aCommand << RC5_EXTENSION_BITS); + // Set the Marantz command extension bits + tIRExtData |= (aMarantzExtension & 0x3F); + + if (aEnableAutomaticToggle) { + if (sLastSendToggleValue == 0) { + sLastSendToggleValue = 1; + // set toggled bit + tIRData |= 1 << (RC5_ADDRESS_BITS); + } else { + sLastSendToggleValue = 0; + } + } + + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; + while (tNumberOfCommands > 0) { + + // start bit is sent by sendBiphaseData folllowed by the field bit and toggle bit and address + sendBiphaseData(RC5_UNIT, tIRData, RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); + // pause before the bits of command and command extension to indicate that it's Marantz-RC5x + space(4 * RC5_UNIT); // Marantz-RC5x has a pause before the bits of command and command extension + // send command and command extension + sendBiphaseData(RC5_UNIT, tIRExtData, RC5_COMMAND_BITS + RC5_EXTENSION_BITS, false); + + tNumberOfCommands--; + // skip last delay! + if (tNumberOfCommands > 0) { + // send repeated command in a fixed raster + delay(RC5_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI); + } + } +} + /** * @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X. * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. */ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) { - // Set IR carrier frequency + + // Set IR carrier frequency enableIROut (RC5_RC6_KHZ); - uint16_t tIRData = ((aAddress & 0x1F) << RC5_COMMAND_BITS); + uint16_t tIRData = ((aAddress & 0x1F) << (RC5_COMMAND_BITS)); if (aCommand < 0x40) { // Auto discovery of RC5X, set field bit to 1 From e59019d8ef7e5c722b488b20ae6ce9ed9d6b9ddd Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 24 Aug 2025 22:14:06 +0200 Subject: [PATCH 098/133] Marantz-RC5 extension support update (#1314) --- Contributors.md | 1 + Doxyfile | 4 +- examples/AllProtocolsOnLCD/ADCUtils.hpp | 4 +- examples/AllProtocolsOnLCD/LiquidCrystal.cpp | 2 +- examples/SendDemo/SendDemo.ino | 23 +++++----- src/IRSend.hpp | 47 ++++++++++---------- src/ir_RC5_RC6.hpp | 4 +- 7 files changed, 44 insertions(+), 41 deletions(-) diff --git a/Contributors.md b/Contributors.md index 9df2e50aa..0d6ccd937 100644 --- a/Contributors.md +++ b/Contributors.md @@ -34,5 +34,6 @@ These are the active contributors of this project that you may contact if there - [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/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 989a7e859..32355bee3 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -677,13 +677,13 @@ bool isVCCUndervoltageMultipleTimes() { # 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(LOCAL_INFO) Serial.print(sVCCVoltageMillivolt); - Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected: ")); + Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV undervoltage detected: ")); Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter); Serial.println(F(" attempts left")); diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp index 8a6e7fa21..240524a95 100644 --- a/examples/AllProtocolsOnLCD/LiquidCrystal.cpp +++ b/examples/AllProtocolsOnLCD/LiquidCrystal.cpp @@ -283,7 +283,7 @@ void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { 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. + // 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 */ diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index f9e41d1fc..79193aaf0 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -280,7 +280,8 @@ void loop() { # endif delay(DELAY_AFTER_SEND); - Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600")); + Serial.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]; @@ -346,16 +347,6 @@ void loop() { IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Marantz variant of RC5x with 6 command bits and additiaonal 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 additiaonal command extension")); - Serial.flush(); - IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sCommandExtension, sRepeats); - delay(DELAY_AFTER_SEND); - Serial.println(F("Send Sony/SIRCS with 7 command and 5 address bits")); Serial.flush(); IrSender.sendSony(sAddress & 0x1F, sCommand & 0x7F, sRepeats); @@ -396,6 +387,16 @@ 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); diff --git a/src/IRSend.hpp b/src/IRSend.hpp index ccb5fd4bb..dc844a816 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -115,7 +115,6 @@ 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, uint_fast8_t aFeedbackLEDPin) { @@ -136,7 +135,7 @@ void IRsend::begin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin) { // Deprecated void IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) { (void) aEnableLEDFeedback; - begin(aSendPin,aFeedbackLEDPin); + begin(aSendPin, aFeedbackLEDPin); } /** @@ -1085,11 +1084,10 @@ void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const * 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, do not send the trailing space of the start bit + * 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 may 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. @@ -1103,25 +1101,30 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas Serial.print('S'); #endif - uint32_t tMask; +// Data - Biphase code MSB first +// prepare for start with sending the start bit, which is 1 + uint32_t tMask; uint_fast8_t tLastBitValue; bool tNextBitIsOne; -// total number of bits to send including start bit if specified - uint8_t aBitsToSend = aNumberOfBits + (aSendStartBit ? 1 : 0); -// Data - Biphase code MSB first + 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) { -// prepare for start with sending the start bit, which is 1 - tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit - tLastBitValue = 1; // Start bit is a 1 - tNextBitIsOne = 1; // Start bit is a 1 + 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 << (aNumberOfBits - 1); // mask is now set for the MSB of data - tLastBitValue = ((aData & tMask) != 0) ? 1 : 0; // remember the value of the first bit to be sent - tNextBitIsOne = tLastBitValue; + // 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 = aBitsToSend; i > 0; i--) { + + // 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 @@ -1131,8 +1134,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas #endif space(aBiphaseTimeUnit); if (tNextBitIsOne) { - // if next bit is 1 send a single mark - 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); @@ -1143,9 +1145,8 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas #if defined(LOCAL_TRACE) Serial.print('0'); #endif - if (!tLastBitValue) { - // if last bit was 0 send a space - mark(aBiphaseTimeUnit); + if (tLastBitValue == 0) { + mark(aBiphaseTimeUnit); // if next bit is 1 send a single mark } space(aBiphaseTimeUnit); tLastBitValue = 0; diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index c5eb1db65..94cc20f98 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -120,7 +120,7 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarant // Mask bit 7 of command and let field bit 0 aCommand &= 0x3F; } - // Set the command to the 2nd partof data to be sent after the pause + // Set the command to the 2nd part of data to be sent after the pause uint16_t tIRExtData = (aCommand << RC5_EXTENSION_BITS); // Set the Marantz command extension bits tIRExtData |= (aMarantzExtension & 0x3F); @@ -138,7 +138,7 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarant uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { - // start bit is sent by sendBiphaseData folllowed by the field bit and toggle bit and address + // start bit is sent by sendBiphaseData followed by the field bit and toggle bit and address sendBiphaseData(RC5_UNIT, tIRData, RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); // pause before the bits of command and command extension to indicate that it's Marantz-RC5x space(4 * RC5_UNIT); // Marantz-RC5x has a pause before the bits of command and command extension From ee3b9cd8dab1ed61b7d8555b712dbe4a0573a544 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 25 Aug 2025 17:27:46 +0200 Subject: [PATCH 099/133] Added UNKNOWN protocol to printIRSendUsage() --- README.md | 21 +- changelog.md | 14 +- examples/ReceiveDump/ReceiveDump.ino | 3 + examples/SendDemo/SendDemo.ino | 33 +- examples/UnitTest/UnitTest.ino | 38 ++- examples/UnitTest/UnitTest.log | 447 ++++++++++++++------------- keywords.txt | 16 +- src/IRProtocol.h | 2 +- src/IRReceive.hpp | 209 +++++++------ src/IRSend.hpp | 120 ++++++- src/IRremoteInt.h | 16 +- 11 files changed, 560 insertions(+), 359 deletions(-) diff --git a/README.md b/README.md index 03f1dbb31..1be77e02c 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) @@ -71,6 +72,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) + * [Simulate an IR receiver module](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module) * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency) * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol) - [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library) @@ -580,9 +582,17 @@ Repeat frames are sent at a fixed period determined by the protocol. e.g. 110 ms Keep in mind, that **there is no delay after the last sent mark**. If you handle the sending of repeat frames by your own, you must insert sensible delays before the repeat frames to enable correct decoding. +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 -> Onkyo, Samsung32 -> Samsung, SIRC20 -> Sony with 20 bits etc. @@ -752,6 +762,7 @@ However, keep in mind that any weak / disturbed signal from one of the receivers **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 Ω**.
@@ -761,6 +772,10 @@ If you do not require more current than 20 mA, there is no need to use an extern On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:. +## Simulate an IR receiver module +To simulate an IR receiver (such as the TSOP1738) which provides an active-low output, you only need to enable the `USE_NO_SEND_PWM` macro. +In the case you must simulate exotic IR receivers, which provides an active-high output, you also need to enable the `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` macro. + ## 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 requires no polling, runs with 1 MHz.
@@ -913,10 +928,10 @@ Modify them by enabling / disabling them, or change the values if applicable. | `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | | `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the **advantage of more exact PWM generation**, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the **disadvantage of using a hardware timer**, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM generation for each pin without using a shared resource (timer). | | `IR_SEND_DUTY_CYCLE_PERCENT` | 30 | Duty cycle of IR send signal. | -| `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverses the polarity 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_LOW_OUTPUT_FOR_SEND_PIN` | disabled | Reverses the polarity of space level for PWM at the send pin, i.e. space is high. Can be used to connect IR LED between VCC and the send pin. It is like open drain but with electrical active high in its logical inactive state. | +| `USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN` | disabled | Uses or simulates open drain output mode for PWM at send pin. **Attention, active state of open drain is LOW**, so connect the send LED between positive supply and send pin! | | `USE_NO_SEND_PWM` | disabled | Uses no carrier PWM, just simulate an **active low** receiver signal. Used for transferring signal by cable instead of IR. Overrides `SEND_PWM_BY_TIMER` definition. | -| `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` | disabled | Only if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. | +| `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` | disabled | Only evaluated if `USE_NO_SEND_PWM` is enabled. Simulate an **active high** receiver signal instead of an active low signal. | | `DISABLE_CODE_FOR_RECEIVER` | disabled | Disables static receiver code like receive timer ISR handler and static IRReceiver and irparams data. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not required. | | `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my BluePill and my ESP8266 board), where the feedback LED is active low. | | `NO_LED_FEEDBACK_CODE` | disabled | Disables the LED feedback code for send and receive. Saves around 100 bytes program memory for receiving, around 500 bytes for sending and halving the receiver ISR (Interrupt Service Routine) processing time. | diff --git a/changelog.md b/changelog.md index 65118f7ed..0da4b7061 100644 --- a/changelog.md +++ b/changelog.md @@ -1,19 +1,21 @@ # Changelog 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. +- Removed parameter aEnableLEDFeedback in function IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) and IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). +- LED feedback is always enabled for sending. It can only be disabled by using the macro NO_LED_SEND_FEEDBACK_CODE. +- Added output for UNKNOWN protocol to printIRSendUsage(). +- Added experimental sendVelux(). +- Added sendMaranz(). - Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306. - Fixed minor bugs in Denon decoder. -- 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 Velux send function. - +- New handling of MARK_EXCESS_MICROS without strange rounding inconsistency. +- Added experimental threshold decoding. # 4.4.3 - Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN to make the software aware of send LED connected between VCC and send pin. diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 7868f38c3..c0af4cb37 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -136,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/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 79193aaf0..208b1adb3 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -65,6 +65,13 @@ IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRaw //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); @@ -169,7 +176,18 @@ void loop() { /* * 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 */ @@ -180,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); /* diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 4a28f40ea..d9049d2da 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -141,6 +141,14 @@ 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); @@ -281,7 +289,8 @@ void checkReceivedRawData(IRRawDataType aRawData) { PrintULL::print(&Serial, aRawData, HEX); #endif Serial.println(); - IrReceiver.printIRResultAsCArray(&Serial, false, false); + IrReceiver.printIRResultAsCArray(&Serial, false, false); // To be able to easily compare received with sent data + Serial.println(); } } IrReceiver.resume(); @@ -497,11 +506,22 @@ void 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 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 */ @@ -513,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); diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 8412904aa..24cdb3168 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -1,5 +1,5 @@ -START ../src/UnitTest.cpp from Jul 31 2025 -Using library version 4.4.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 400 @@ -7,281 +7,296 @@ Send IR signals at pin 3 If you connect debug pin 5 to ground, raw data is always printed Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us 16000 us is the (minimum) gap, after which the start of a new IR packet is assumed -Threshold decoding is active and thus MARK_EXCESS_MICROS is set to 0 +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, Gap=753700us, Duration=67800us +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]: - -753700 - +8950,-4350 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 - + 600,- 550 + 600,-1600 + 650,-1600 + 600,-1650 - + 600,- 500 + 650,- 500 + 600,- 500 + 600,- 550 - + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 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 -Duration=67800us +Duration=67900us Send NEC with 16 bit address -Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764300us, Duration=73350us +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]: - -764300 - +8950,-4400 - + 600,-1600 + 650,- 500 + 650,- 450 + 650,- 500 - + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 - + 600,-1650 + 600,-1600 + 600,-1650 + 650,-1600 - + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 +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=73350us +Duration=73400us Send NEC2 with 16 bit address -Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764750us, Duration=73350us +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]: - -764750 +rawIRTimings[68]: + -765200 +8950,-4400 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550 - + 600,-1600 + 650,-1600 + 600,-1650 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 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=73350us +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 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, Gap=773500us, Duration=67800us +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, ); -rawData[68]: - -773500 +rawIRTimings[68]: + -756450 +9100,-4350 - + 650,- 450 + 650,- 500 + 650,- 550 + 600,- 550 - + 650,- 500 + 650,- 500 + 650,- 500 + 650,-1600 - + 650,-1550 + 650,-1550 + 650,-1600 + 600,-1550 - + 650,-1550 + 650,-1600 + 600,-1600 + 650,- 450 - + 650,-1550 + 650,- 500 + 650,-1600 + 650,- 500 - + 600,- 500 + 700,- 450 + 650,-1600 + 600,- 550 - + 650,- 450 + 750,-1450 + 650,- 500 + 650,-1600 - + 600,-1600 + 600,-1600 + 650,- 500 + 650,-1550 - + 650 -Duration=67800us - - -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, Gap=770700us, Duration=68050us + + 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, ); -rawData[68]: - -770700 - +8950,-4400 - + 650,- 500 + 650,- 500 + 600,-1650 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,- 500 + 650,-1600 +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 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500 - + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + 600 -Duration=68050us +Duration=68100us Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102) -Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=768950us, Duration=55600us +Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=769500us, Duration=55700us Send with: IrSender.sendOnkyo(0x102, 0x304, ); -rawData[68]: - -768950 - +8950,-4400 - + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,-1600 + 600,-1600 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500 - + 600 -Duration=55600us +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=770950us, Duration=61100us +Protocol=NEC Address=0x102, Command=0x34, Raw-Data=0xCB340102, 32 bits, LSB first, Gap=771400us, Duration=61250us Send with: IrSender.sendNEC(0x102, 0x34, ); -rawData[68]: - -770950 - +8900,-4400 - + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500 - + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 - + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,- 500 + 600,- 500 - + 650,-1600 + 650,-1600 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600 - + 600 -Duration=61100us +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=770400us, Duration=54150us +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]: - -770400 +rawIRTimings[100]: + -770850 +3450,-1700 - + 500,- 400 + 450,-1250 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 450,- 400 - + 500,- 350 + 500,-1250 + 500,- 350 + 500,- 400 - + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 - + 500,-1250 + 450,-1250 + 500,- 400 + 450,-1250 - + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 350 - + 500,- 400 + 500,- 350 + 500,- 350 + 500,- 400 - + 500,- 400 + 500,- 350 + 450,- 450 + 450,- 400 - + 500,-1200 + 450,- 450 + 450,- 400 + 500,- 350 - + 500,- 350 + 500,- 400 + 450,- 400 + 450,- 450 - + 450,- 400 + 450,-1250 + 450,- 450 + 500,-1200 - + 450 -Duration=54150us + + 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 PGM 1=450|1250, 0=450|400 -LSB first -Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=787100us, Duration=53200us +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]: - -787100 - +3500,-1650 - + 450,- 400 + 450,-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,- 400 - + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,-1200 + 500,-1200 + 500,- 350 + 500,-1200 +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,- 350 + 500,- 350 + 500,- 350 + 500,- 400 - + 450,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,-1200 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,- 350 + 500,- 400 + 450,- 350 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1200 - + 500 -Duration=53200us + + 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, Gap=779800us, Duration=53200us +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]: - -779800 - +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,- 400 - + 450,-1200 + 500,- 350 + 500,- 350 + 550,- 300 - + 500,- 350 + 500,- 350 + 500,- 350 + 500,- 350 - + 500,- 350 + 500,-1200 + 500,- 350 + 500,-1200 - + 500 -Duration=53200us +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 1=550|1700, 0=550|600 -Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=786600us, Duration=138350us +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, 8900, 4350, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); -rawData[148]: - -786600 - +8900,-4350 - + 600,-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,-1700 - + 550,-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 - + 550,- 600 + 550,-1650 + 600,-1650 + 600,-1650 - + 600,-1650 + 600,-1650 + 600,-1650 + 550,-1700 - + 550,- 600 + 550,-1650 + 600,- 550 + 600,-1650 - + 600,- 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 -Duration=138350us +Duration=139050us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300 -Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822500us, Duration=48200us +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, 350, 550, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[108]: - -822500 - + 350,- 550 - + 350,- 550 + 650,- 250 + 700,- 200 + 650,- 250 - + 700,- 200 + 400,- 550 + 600,- 250 + 650,- 250 - + 400,- 550 + 350,- 550 + 600,- 250 + 650,- 250 - + 650,- 250 + 700,- 200 + 400,- 500 + 650,- 250 - + 400,- 550 + 600,- 250 + 350,- 600 + 600,- 300 - + 600,- 300 + 350,- 550 + 300,- 600 + 600,- 300 - + 350,- 550 + 300,- 600 + 350,- 550 + 600,- 300 - + 600,- 300 + 600,- 300 + 600,- 250 + 400,- 550 - + 350,- 550 + 650,- 250 + 650,- 250 + 400,- 500 - + 650,- 250 + 350,- 600 + 600,- 300 + 350,- 550 - + 350,- 550 + 350,- 600 + 600,- 250 + 350,- 600 - + 600,- 300 + 600,- 300 + 300,- 600 + 300,- 550 - + 400,- 550 + 600,- 300 + 350,- 550 + 350,- 550 - + 350 -Duration=48200us + 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=802750us, Duration=48450us +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, 600, 350, 550, 600, 300, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); -rawData[108]: - -802750 + 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 + 600,- 300 + 600,- 300 + 600,- 300 - + 600,- 300 + 350,- 550 + 600,- 300 + 600,- 300 - + 350,- 550 + 350,- 550 + 600,- 300 + 600,- 300 - + 600,- 300 + 600,- 300 + 350,- 550 + 600,- 300 - + 350,- 550 + 600,- 300 + 300,- 600 + 600,- 300 - + 600,- 300 + 350,- 550 + 350,- 550 + 650,- 250 - + 350,- 600 + 350,- 550 + 350,- 550 + 600,- 300 - + 600,- 300 + 600,- 300 + 600,- 300 + 350,- 550 - + 350,- 550 + 650,- 250 + 650,- 250 + 400,- 500 - + 650,- 250 + 350,- 550 + 650,- 300 + 300,- 550 - + 350,- 600 + 350,- 550 + 600,- 250 + 350,- 600 - + 600,- 300 + 600,- 250 + 350,- 550 + 400,- 550 - + 300,- 600 + 600,- 300 + 350,- 550 + 350,- 550 - + 600 -Duration=48450us + + 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 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500 diff --git a/keywords.txt b/keywords.txt index 5f05f9d1a..03bdd2891 100644 --- a/keywords.txt +++ b/keywords.txt @@ -42,24 +42,30 @@ end KEYWORD2 # IRSend setSendPin KEYWORD2 write KEYWORD2 -sendRaw KEYWORD2 +sendApple KEYWORD2 +sendFAST KEYWORD2 sendJVC KEYWORD2 +sendLegoPowerFunctions KEYWORD2 sendLG 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 @@ -67,11 +73,7 @@ sendSamsung KEYWORD2 sendSharp KEYWORD2 sendSony KEYWORD2 sendSharpRaw KEYWORD2 -sendLegoPowerFunctions KEYWORD2 -sendMagiQuest KEYWORD2 -sendPronto KEYWORD2 -sendMagiQuest KEYWORD2 -sendFAST KEYWORD2 +sendVelux KEYWORD2 # IRFeedbackLED disableLEDFeedback KEYWORD2 diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 258aaf5b2..c9dd24cd4 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -163,7 +163,7 @@ struct PulseDistanceWidthProtocolConstants { 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)(); }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index ba4780667..712545d53 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -50,7 +50,6 @@ //#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 @@ -1116,6 +1115,7 @@ IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProto void IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) { + PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, sizeof(tTemporaryPulseDistanceWidthProtocolConstants)); @@ -1968,6 +1968,8 @@ uint32_t IRrecv::getTotalDurationOfRawData() { 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. @@ -1977,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) { @@ -1988,113 +2000,134 @@ 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: ")); - tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1; - if(tNumberOfArrayData > 1) { - aSerial->println(); - aSerial->print(F(" uint64_t tRawData[]={0x")); -# endif - 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); + 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")); + for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) { + PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX); # endif - if (i != tNumberOfArrayData - 1) { - aSerial->print(F(", 0x")); - } + if (i != tNumberOfArrayData - 1) { + aSerial->print(F(", 0x")); } - aSerial->println(F("};")); - aSerial->print(F(" ")); } - } else { - aSerial->print(F("Send with: ")); + aSerial->println(F("};")); + aSerial->print(F(" ")); } - aSerial->print(F("IrSender.send")); + } 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 if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) { + /* + * Pulse distance or pulse width here + */ + aSerial->print(F("PulseDistanceWidth")); + if(tNumberOfArrayData > 1) { + aSerial->print(F("FromArray(38, ")); } else { - /* - * Pulse distance or pulse width here - */ - aSerial->print(F("PulseDistanceWidth")); - if(tNumberOfArrayData > 1) { - aSerial->print(F("FromArray(38, ")); - } else { - aSerial->print(F("(38, ")); - } - printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo); + aSerial->print(F("(38, ")); + } + printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo); - if(tNumberOfArrayData > 1) { - aSerial->print(F(", &tRawData[0], ")); - } else { - aSerial->print(F(", 0x")); + if(tNumberOfArrayData > 1) { + aSerial->print(F(", &tRawData[0], ")); + } else { + 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 - aSerial->print(F(", ")); - } - aSerial->print(decodedIRData.numberOfBits); // aNumberOfBits - aSerial->print(F(", PROTOCOL_IS_")); + aSerial->print(F(", ")); + } + aSerial->print(decodedIRData.numberOfBits); // aNumberOfBits + aSerial->print(F(", PROTOCOL_IS_")); - if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) { - aSerial->print('M'); - } else { - aSerial->print('L'); - } - aSerial->print(F("SB_FIRST, , ")); + if (decodedIRData.flags & IRDATA_FLAGS_IS_MSB_FIRST) { + aSerial->print('M'); + } else { + aSerial->print('L'); } + 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) || defined(DECODE_RC6) - if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A)) { - aSerial->print(F(", 0x")); - aSerial->print(decodedIRData.extra, HEX); + + 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); + } #endif aSerial->print(F(");")); aSerial->println(); } } +// @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(). @@ -2167,7 +2200,7 @@ void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTi void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) { // Print Raw data - aSerial->print(F("rawData[")); + aSerial->print(F("rawIRTimings[")); aSerial->print(decodedIRData.rawlen); aSerial->println(F("]: ")); @@ -2269,7 +2302,7 @@ void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicr 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 } @@ -2310,9 +2343,6 @@ void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInste // Comment aSerial->print(F(" // ")); printIRResultShort(aSerial); - -// Newline - aSerial->println(); } /** @@ -2369,9 +2399,9 @@ 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); @@ -2379,7 +2409,6 @@ void IRrecv::printIRResultAsCVariables(Print *aSerial) { PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); #endif aSerial->println(';'); - aSerial->println(); } } diff --git a/src/IRSend.hpp b/src/IRSend.hpp index dc844a816..121e5ca2d 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -414,6 +414,32 @@ 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); + } + } + } +} /** * Sends an 8 byte tick timing array to save program memory. @@ -431,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); @@ -469,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); @@ -495,13 +571,34 @@ 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 @@ -874,6 +971,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc } tNumberOfCommands--; + // skip last delay! if (tNumberOfCommands > 0) { auto tCurrentFrameDurationMillis = millis() - tStartOfFrameMillis; diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index f858b3267..1c52c6afa 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -597,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 @@ -616,9 +624,7 @@ class IRsend { void sendBoseWave(uint8_t aCommand, int_fast8_t aNumberOfRepeats = NO_REPEATS); 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); @@ -646,7 +652,7 @@ class IRsend { 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); + 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); From 251d34b91f28026d930e22c0c7617806ee42bf36 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 8 Oct 2025 19:25:55 +0200 Subject: [PATCH 100/133] Closes #1322 --- .github/workflows/LibraryBuild.yml | 50 +++++++++++++++--------------- README.md | 6 ++-- src/IRProtocol.h | 2 ++ src/TinyIR.h | 2 +- src/TinyIRReceiver.hpp | 2 +- src/TinyIRSender.hpp | 2 +- 6 files changed, 33 insertions(+), 31 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index eacec58e1..edc0b8758 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -62,9 +62,9 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect - - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll - - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled - - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz +# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll +# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled +# - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=8MHz_internal # ATmega128 - SparkFun:avr:promicro - megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal @@ -200,28 +200,28 @@ jobs: # # 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,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 +# - 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 diff --git a/README.md b/README.md index 1be77e02c..626a3a55c 100644 --- a/README.md +++ b/README.md @@ -980,11 +980,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**, [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)
+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 tested with **[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore) only**. +Digispark boards are tested only with [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using the `New Style` pin mapping for the Digispark Pro board.
+**ATtiny boards** are tested only with **[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore#supported-devices) or [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore)**. - Arduino Uno / Mega / Leonardo / Duemilanove / Diecimila / LilyPad / Mini / Fio / Nano etc. - Arduino Uno R4, but not yet tested, because of lack of a R4 board. **Sending does not work** on the `arduino:renesas_uno:unor4wifi`. diff --git a/src/IRProtocol.h b/src/IRProtocol.h index c9dd24cd4..258204d1b 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -32,6 +32,8 @@ #ifndef _IR_PROTOCOL_H #define _IR_PROTOCOL_H +#include + /* * If activated, BANG_OLUFSEN, BOSEWAVE, MAGIQUEST, WHYNTER, FAST and LEGO_PF are excluded in decoding and in sending with IrSender.write */ diff --git a/src/TinyIR.h b/src/TinyIR.h index ea1ce7bf5..19845d02d 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -5,8 +5,8 @@ * Copyright (C) 2021-2025 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * - * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * * TinyIRReceiver is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index cd5fe88e8..1bfa9258d 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -22,8 +22,8 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * - * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 1053d52c7..9412d3204 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -13,8 +13,8 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * - * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License From 93cfd571353a8809f12688b269eca6e9570b0462 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 19 Oct 2025 21:49:33 +0200 Subject: [PATCH 101/133] Closes #1324 --- Contributors.md | 1 + examples/AllProtocolsOnLCD/ADCUtils.h | 5 ++ examples/AllProtocolsOnLCD/ADCUtils.hpp | 53 ++++++++++++++++++- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 2 +- ...dCrystal_I2C.cpp => LiquidCrystal_I2C.hpp} | 2 +- examples/TinyReceiver/TinyReceiver.ino | 4 +- examples/TinySender/TinySender.ino | 2 +- src/private/IRTimer.hpp | 36 +++++++++---- 8 files changed, 88 insertions(+), 17 deletions(-) rename examples/AllProtocolsOnLCD/{LiquidCrystal_I2C.cpp => LiquidCrystal_I2C.hpp} (99%) diff --git a/Contributors.md b/Contributors.md index 0d6ccd937..90a817a19 100644 --- a/Contributors.md +++ b/Contributors.md @@ -35,5 +35,6 @@ These are the active contributors of this project that you may contact if there - [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. +- [silen72](https://github.com/silen72) Fixing ESP32 multiple attach bug #1324. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 33c2bbfc1..20d759b4c 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -31,6 +31,7 @@ // 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 +#define MAX_ADC_VALUE 1023L // 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 @@ -172,8 +173,10 @@ extern long sLastVCCCheckMillis; extern uint8_t sVCCTooLowCounter; +uint16_t readADCChannel(); uint16_t readADCChannel(uint8_t aADCChannelNumber); uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); +uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber); uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference); uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent); @@ -188,6 +191,8 @@ uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay, uint8_t aAllowedDifference, uint8_t aMaxRetries); +void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber); +void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber); uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference); /* diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 32355bee3..e7a2124c0 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -42,7 +42,7 @@ * with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV. */ #if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT) -#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100L // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values +#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100UL // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values #endif // Union to speed up the combination of low and high bytes to a word @@ -85,6 +85,27 @@ uint8_t sVCCTooLowCounter = 0; /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. + * Use previous settings + */ +uint16_t readADCChannel() { + WordUnionForADCUtils tUValue; + + // ADCSRB = 0; // Only active if ADATE is set to 1. + // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE); + + // wait for single conversion to finish + loop_until_bit_is_clear(ADCSRA, ADSC); + + // Get value + tUValue.UByte.LowByte = ADCL; + tUValue.UByte.HighByte = ADCH; + return tUValue.UWord; + // return ADCL | (ADCH <<8); // needs 4 bytes more +} + +/* + * Use new channel aADCChannelNumber, but do not wait for channel switching */ uint16_t readADCChannel(uint8_t aADCChannelNumber) { WordUnionForADCUtils tUValue; @@ -103,7 +124,6 @@ uint16_t readADCChannel(uint8_t aADCChannelNumber) { return tUValue.UWord; // return ADCL | (ADCH <<8); // needs 4 bytes more } - /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. */ @@ -124,6 +144,22 @@ uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReferen return tUValue.UWord; } +uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber) { + WordUnionForADCUtils tUValue; + ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE); + + // ADCSRB = 0; // Only active if ADATE is set to 1. + // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE); + + // wait for single conversion to finish + loop_until_bit_is_clear(ADCSRA, ADSC); + + // Get value + tUValue.UByte.LowByte = ADCL; + tUValue.UByte.HighByte = ADCH; + return tUValue.UWord; +} /* * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h. * Does NOT restore ADMUX after reading @@ -151,6 +187,19 @@ void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8 ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE); } +/* + * 100 kOhm requires < 100 us, 1 MOhm requires 120 us S&H switching time + */ +void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber) { + ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE); + delayMicroseconds(120); // experimental value is <= 1100 us for Nano board +} + +void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber) { + ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE); + delayMicroseconds(120); // experimental value is <= 1100 us for Nano board +} + /* * @return original ADMUX register content for optional later restoring values * All experimental values are acquired by using the ADCSwitchingTest example from this library diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 668922eb8..01289bbc0 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -86,7 +86,7 @@ #define LCD_ROWS 2 #if defined(USE_SERIAL_LCD) -#include "LiquidCrystal_I2C.h" // Use an up to date library version, which has the init method +#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster LiquidCrystal_I2C myLCD(0x27, LCD_COLUMNS, LCD_ROWS); // set the LCD address to 0x27 for a 16 chars and 2 line display #elif !defined(USE_NO_LCD) #define USE_PARALLEL_LCD diff --git a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp similarity index 99% rename from examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp rename to examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp index 7ac4cead0..d8de0ef42 100644 --- a/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.cpp +++ b/examples/AllProtocolsOnLCD/LiquidCrystal_I2C.hpp @@ -14,7 +14,7 @@ #include "Arduino.h" #if defined(__AVR__) && !defined(USE_SOFT_I2C_MASTER) && __has_include("SoftI2CMasterConfig.h") -#define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.h" +#define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.hpp" #endif #include "LiquidCrystal_I2C.h" diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index b31b4657f..05ae22cd7 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -20,13 +20,13 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * - * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * 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 diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index 4af49883b..d0753b645 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -17,8 +17,8 @@ * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * - * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index ac893cc1d..bb04b0559 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1671,7 +1671,8 @@ void timerConfigForReceive() { } # endif -uint8_t sLastSendPin = 0; // Avoid multiple attach() or if pin changes, detach before attach +uint8_t sLastSendPin = 0; // 0 means channel not initialized / pin not attached +uint16_t sLastFrequencyKHz = 0; # if defined(SEND_PWM_BY_TIMER) void enableSendPWMByTimer() { @@ -1718,27 +1719,42 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { # if ESP_ARDUINO_VERSION >= (3 << 16 | 0 << 8 | 0) # if defined(IR_SEND_PIN) if(sLastSendPin == 0){ - ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API + // Do it only once - except for frequency change + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); sLastSendPin = IR_SEND_PIN; + } else if(sLastFrequencyKHz != aFrequencyKHz){ + // Frequency change here + ledcDetach(IR_SEND_PIN); // detach pin before new attaching see #1194 + ledcAttach(IR_SEND_PIN, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API + sLastFrequencyKHz = aFrequencyKHz; } # else - if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ - ledcDetach(IrSender.sendPin); // detach pin before new attaching see #1194 + if(sLastSendPin != IrSender.sendPin || sLastFrequencyKHz != aFrequencyKHz){ + if(sLastSendPin != 0) { + // do not detach initially + ledcDetach(sLastSendPin); // detach pin before new attaching see #1194 + } + ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API + sLastSendPin = IrSender.sendPin; + sLastFrequencyKHz = aFrequencyKHz; } - ledcAttach(IrSender.sendPin, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 3.x API - sLastSendPin = IrSender.sendPin; # endif # else - // ESP version < 3.0 + // ESP version < 3.0 - no support for changing frequency ledcSetup(SEND_LEDC_CHANNEL, aFrequencyKHz * 1000, _IRREMOTE_ESP32_LEDC_RESOLUTION); // 8 bit PWM resolution # if defined(IR_SEND_PIN) ledcAttachPin(IR_SEND_PIN, SEND_LEDC_CHANNEL); // attach pin to channel # else if(sLastSendPin != 0 && sLastSendPin != IrSender.sendPin){ - ledcDetachPin(IrSender.sendPin); // detach pin before new attaching see #1194 } - ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel - sLastSendPin = IrSender.sendPin; + if( sLastSendPin != IrSender.sendPin){ + if(sLastSendPin != 0) { + // do not detach initially + ledcDetachPin(sLastSendPin); // detach pin before new attaching see #1194 + } + ledcAttachPin(IrSender.sendPin, SEND_LEDC_CHANNEL); // attach pin to channel + sLastSendPin = IrSender.sendPin; + } # endif # endif } From ed56ff7dc54469b40d44de03c1a865b54086ba86 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 7 Nov 2025 18:01:35 +0100 Subject: [PATCH 102/133] Housekeeping --- README.md | 3 +- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 103 ++--- examples/AllProtocolsOnLCD/LCDPrintUtils.hpp | 403 ++++++++++++++++++ .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 2 +- .../IRDispatcherDemo/IRCommandDispatcher.hpp | 2 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/MicroGirs/PinDefinitionsAndMore.h | 2 +- .../MultipleReceivers/PinDefinitionsAndMore.h | 2 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 2 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/SimpleSender/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/TinyReceiver.ino | 2 +- examples/TinySender/PinDefinitionsAndMore.h | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 2 +- src/ir_DistanceWidthProtocol.hpp | 6 +- 31 files changed, 474 insertions(+), 95 deletions(-) create mode 100644 examples/AllProtocolsOnLCD/LCDPrintUtils.hpp diff --git a/README.md b/README.md index 626a3a55c..ee5c72624 100644 --- a/README.md +++ b/README.md @@ -1187,7 +1187,8 @@ It is dated from **24.06.2022** and updated 10/2023. If you have complains about - [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols) - [Good introduction to IR remotes by DroneBot Workshop](https://dronebotworkshop.com/ir-remotes/) - [IR Remote Control Theory and some protocols (upper right hamburger icon)](https://www.sbprojects.net/knowledge/ir/) -- [Interpreting Decoded IR Signals (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html) +- [Overviev of many protocols](https://www.hifi-remote.com/wiki/index.php/Category:DecodeIR) +- [Overviev of many protocols on one page (v2.45)](http://www.hifi-remote.com/johnsfine/DecodeIR.html) - ["Recording long Infrared Remote control signals with Arduino"](https://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino) - The original blog post of Ken Shirriff [A Multi-Protocol Infrared Remote Library for the Arduino](http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html) - [Vishay datasheet](https://www.vishay.com/docs/80069/circuit.pdf) diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 01289bbc0..02758ea51 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -80,19 +80,30 @@ * because of the long lasting serial communication. */ //#define USE_NO_LCD -//#define USE_SERIAL_LCD -// Definitions for the 1602 LCD -#define LCD_COLUMNS 16 -#define LCD_ROWS 2 - -#if defined(USE_SERIAL_LCD) -#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster +#if !defined(USE_NO_LCD) +#define USE_LCD +#define USE_PARALLEL_2004_LCD // Is default +//#define USE_SERIAL_1602_LCD +#include "LCDPrintUtils.hpp" // sets USE_PARALLEL_LCD or USE_SERIAL_LCD +# if defined(USE_SERIAL_LCD) LiquidCrystal_I2C myLCD(0x27, LCD_COLUMNS, LCD_ROWS); // set the LCD address to 0x27 for a 16 chars and 2 line display -#elif !defined(USE_NO_LCD) -#define USE_PARALLEL_LCD -#include "LiquidCrystal.h" +# else //LiquidCrystal myLCD(4, 5, 6, 7, 8, 9); LiquidCrystal myLCD(7, 8, 3, 4, 5, 6); +# endif +# if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) +// For cyclically display of VCC and isVCCUSBPowered() +#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4250 +#include "ADCUtils.hpp" +#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000 +#define LCD_VOLTAGE_START_INDEX 11 +uint32_t volatile sMillisOfLastVoltagePrint = 0; +bool ProtocolStringOverwritesVoltage = false; +# endif +#define LCD_IR_COMMAND_START_INDEX 9 + +void printsVCCVoltageMillivoltOnLCD(); +void printIRResultOnLCD(); #endif #if defined(USE_PARALLEL_LCD) @@ -109,26 +120,6 @@ LiquidCrystal myLCD(7, 8, 3, 4, 5, 6); #define MILLIS_BETWEEN_ATTENTION_BEEP 60000 // 60 sec uint32_t sMillisOfLastReceivedIRFrame = 0; -#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD) -#define USE_LCD -# if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) -// For cyclically display of VCC and isVCCUSBPowered() -#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4250 -#include "ADCUtils.hpp" -#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000 -#define LCD_VOLTAGE_START_INDEX 11 -uint32_t volatile sMillisOfLastVoltagePrint = 0; -bool ProtocolStringOverwritesVoltage = false; -# endif -#define LCD_IR_COMMAND_START_INDEX 9 - -void printsVCCVoltageMillivoltOnLCD(); -void printIRResultOnLCD(); -size_t printByteHexOnLCD(uint16_t aHexByteValue); -void printSpacesOnLCD(int_fast8_t aNumberOfSpacesToPrint); - -#endif // defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD) - void setup() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. pinMode(DEBUG_BUTTON_PIN, INPUT_PULLUP); @@ -352,39 +343,37 @@ void printIRResultOnLCD() { // we overwrite the voltage -> clear rest of line and inhibit new printing of voltage ProtocolStringOverwritesVoltage = true; if (tProtocolStringLength < LCD_COLUMNS) { - printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength); + LCDPrintSpaces(&myLCD, LCD_COLUMNS - tProtocolStringLength); } } else { // Trigger printing of VCC in main loop sMillisOfLastVoltagePrint = 0; ProtocolStringOverwritesVoltage = false; - printSpacesOnLCD(LCD_VOLTAGE_START_INDEX - tProtocolStringLength); + LCDPrintSpaces(&myLCD, LCD_VOLTAGE_START_INDEX - tProtocolStringLength); } # else - printSpacesOnLCD(LCD_COLUMNS - tProtocolStringLength); + LCDPrintSpaces(&myLCD, LCD_COLUMNS - tProtocolStringLength); # endif } if (IrReceiver.decodedIRData.protocol == UNKNOWN) { /* - * Print number of bits received and hash code or microseconds of signal + * Print number of bits received and hash code + * "123 bit 5E7E4778" */ myLCD.setCursor(0, 1); uint8_t tNumberOfBits = (IrReceiver.irparams.rawlen + 1) / 2; - uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits); - myLCD.print(F(" bit ")); + uint_fast8_t tPrintedStringLength = myLCD.print(tNumberOfBits); // tPrintedStringLength = 1 to 3 + myLCD.print(F(" bit ")); // 5 characters if (tNumberOfBits < 10) { - myLCD.print('0'); - tPrintedStringLength++; - } - if (tNumberOfBits < 100) { - myLCD.print('x'); + myLCD.print(F("0x")); + tPrintedStringLength += 2; } - tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX) + 1; - printSpacesOnLCD(11 - tPrintedStringLength); + tPrintedStringLength += myLCD.print(IrReceiver.decodedIRData.decodedRawData, HEX); // maximum is += 8; + LCDPrintSpaces(&myLCD, (LCD_COLUMNS - 5) - tPrintedStringLength); sLastProtocolAddress = 4711; - sLastCommand = 44711; + sLastCommand = 4711; } else { /* @@ -403,7 +392,7 @@ void printIRResultOnLCD() { sLastProtocolAddress = 4711; // To enforce next print of address myLCD.print(F("[0]=0x")); uint_fast8_t tAddressStringLength = myLCD.print(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX); - printSpacesOnLCD(LCD_COLUMNS - tAddressStringLength); + LCDPrintSpaces(&myLCD, LCD_COLUMNS - tAddressStringLength); sLastCommand = 0; // to trigger restoration of "C=" string, if another protocol is received /* * No command here! @@ -416,8 +405,8 @@ void printIRResultOnLCD() { // Serial.print(F("Print address 0x")); // Serial.println(IrReceiver.decodedIRData.address, HEX); myLCD.print(F("A=")); - uint_fast8_t tAddressStringLength = printByteHexOnLCD(IrReceiver.decodedIRData.address); - printSpacesOnLCD((LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength); + uint_fast8_t tAddressStringLength = LCDPrintHex(&myLCD, IrReceiver.decodedIRData.address); + LCDPrintSpaces(&myLCD, (LCD_IR_COMMAND_START_INDEX - 2) - tAddressStringLength); # if defined(DECODE_DISTANCE_WIDTH) } # endif @@ -452,7 +441,7 @@ void printIRResultOnLCD() { // Serial.print(F(" at ")); // Serial.println(sLastCommandPrintPosition); myLCD.setCursor(sLastCommandPrintPosition, 1); - printByteHexOnLCD(tCommand); + LCDPrintHex(&myLCD, tCommand); /* * Show or clear repetition flag @@ -465,22 +454,4 @@ void printIRResultOnLCD() { } } // IrReceiver.decodedIRData.protocol == UNKNOWN } - -size_t printByteHexOnLCD(uint16_t aHexByteValue) { - myLCD.print(F("0x")); - size_t tPrintSize = 2; - if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) { - myLCD.print('0'); // leading 0 - tPrintSize++; - } - return myLCD.print(aHexByteValue, HEX) + tPrintSize; -} - -void printSpacesOnLCD(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/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp new file mode 100644 index 000000000..92a6378bb --- /dev/null +++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp @@ -0,0 +1,403 @@ +/* + * LCDPrintUtils.hpp + * + * Contains LCD related variables and functions + * Sets symbols USE_SERIAL_LCD or USE_PARALLEL_LCD and LCD_COLUMNS and LCD_ROWS + * + * Copyright (C) 2024-2025 Armin Joachimsmeyer + * Email: armin.joachimsmeyer@gmail.com + * + * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. + * + * Arduino-Utils is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _LCD_PRINT_UTILS_HPP +#define _LCD_PRINT_UTILS_HPP + +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development + +//#define USE_PARALLEL_2004_LCD // Is default +//#define USE_PARALLEL_1602_LCD +//#define USE_SERIAL_2004_LCD +//#define USE_SERIAL_1602_LCD + +#if !defined(USE_PARALLEL_2004_LCD) && !defined(USE_PARALLEL_1602_LCD) && !defined(USE_SERIAL_2004_LCD) && !defined(USE_SERIAL_1602_LCD) +#warning "No LCD type like USE_SERIAL_2004_LCD specified, therefore using USE_PARALLEL_2004_LCD as default" +#define USE_PARALLEL_2004_LCD // Use parallel 2004 LCD as default +#endif + +#if defined(USE_PARALLEL_2004_LCD) || defined(USE_PARALLEL_1602_LCD) +#define USE_PARALLEL_LCD +# if defined(USE_PARALLEL_2004_LCD) +#define LCD_COLUMNS 20 +#define LCD_ROWS 4 +# else +#define LCD_COLUMNS 16 +#define LCD_ROWS 2 +# endif +#include "LiquidCrystal.h" +#else +#define USE_SERIAL_LCD +# if defined(USE_SERIAL_2004_LCD) +#define LCD_COLUMNS 20 +#define LCD_ROWS 4 +# else +#define LCD_COLUMNS 16 +#define LCD_ROWS 2 +# endif +#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster +#endif + +/* + * Helper macro for getting a macro definition as string + */ +#if !defined(STR_HELPER) && !defined(STR) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif + +#define DEGREE_SIGN_STRING "\xDF" + +extern char sStringBuffer[]; // For rendering a LCD row with snprintf_P() + +#if defined(USE_PARALLEL_LCD) +void LCDResetCursor(LiquidCrystal *aLCD); +void LCDPrintSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint); +void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber); +size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue); +void LCDPrintAsFloatAs5CharacterString(LiquidCrystal *aLCD, uint16_t aValueInMillivolts); +void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, + bool aNoLeadingSpaceForPositiveValues = false); +void LCDTestPrintFloatValueRightAligned(LiquidCrystal *aLCD); +void LCDShowSpecialCharacters(LiquidCrystal *aLCD); +void LCDShowCustomCharacters(LiquidCrystal *aLCD); +#else +void LCDResetCursor(LiquidCrystal_I2C *aLCD); +void LCDPrintSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint); +void LCDClearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber); +size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue); +void LCDPrintAsFloatAs5CharacterString(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts); +void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, + bool aNoLeadingSpaceForPositiveValues = false); +void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD); +void LCDShowSpecialCharacters(LiquidCrystal_I2C *aLCD); +void LCDShowCustomCharacters(LiquidCrystal_I2C *aLCD); +#endif +uint8_t getNumberOfDecimalsFor16BitValues(uint16_t a16BitValue); + +/* + * Code starts here + */ + +#if defined(USE_PARALLEL_LCD) +void LCDResetCursor(LiquidCrystal *aLCD) +#else +void LCDResetCursor(LiquidCrystal_I2C *aLCD) +#endif + { + aLCD->setCursor(0, 0); +} + +#if defined(USE_PARALLEL_LCD) +void LCDPrintSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint) +#else +void LCDPrintSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint) +#endif + { + for (uint_fast8_t i = 0; i < aNumberOfSpacesToPrint; ++i) { + aLCD->print(' '); + } +} + +#if defined(USE_PARALLEL_LCD) +void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber) +#else +void LCDClearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber) +#endif + { + aLCD->setCursor(0, aLineNumber); + LCDPrintSpaces(aLCD, LCD_COLUMNS); + aLCD->setCursor(0, aLineNumber); +} + +#if defined(USE_PARALLEL_LCD) +size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue) +#else +size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue) +#endif + { + aLCD->print(F("0x")); + size_t tPrintSize = 2; + if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) { + aLCD->print('0'); // leading 0 + tPrintSize++; + } + return aLCD->print(aHexByteValue, HEX) + tPrintSize; +} + +/* + * Use 2 decimals, if value is >= 10 + */ +#if defined(USE_PARALLEL_LCD) +void LCDPrintAsFloatAs5CharacterString(LiquidCrystal *aLCD, uint16_t aValueInMillivolts) +#else +void LCDPrintAsFloatAs5CharacterString(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts) +#endif + { + if (aValueInMillivolts < 10000) { + aLCD->print(((float) (aValueInMillivolts)) / 1000, 3); + } else { + aLCD->print(((float) (aValueInMillivolts)) / 1000, 2); + } +} + +/* + * @return 1 for values from 0 to 9, 2 for 10 to 99 up to 5 for >= 10,000 + */ +uint8_t getNumberOfDecimalsFor16BitValues(uint16_t a16BitValue) { + uint16_t tCompareValue = 1; + /* + * Check for 10, 100, 1000 + */ + for (uint_fast8_t tNumberOfDecimals = 0; tNumberOfDecimals < 5; ++tNumberOfDecimals) { + if (a16BitValue < tCompareValue) { + return tNumberOfDecimals; + } + tCompareValue *= 10; + } + // here we have values >= 10,000 + return 5; +} + +/* + * @return 1 for values from 0 to 9, 2 for 10 to 99 up to 10 for >= 1,000,000,000 + * Requires 26 bytes more program space than getNumberOfDecimalsFor16BitValues() + */ +uint8_t getNumberOfDecimalsFor32BitValues(uint32_t a32BitValue) { + uint_fast8_t tNumberOfDecimals = 1; + uint32_t tCompareValue = 10; + /* + * Check for 10, 100, 1000 up to 100,000,000 + */ + for (; tNumberOfDecimals < 10; ++tNumberOfDecimals) { + if (a32BitValue < tCompareValue) { + return tNumberOfDecimals; + } + tCompareValue *= 10; + } + // here we have values >= 1,000,000,000 + return 10; +} +/* + * !!! We internally use uint16_t, thus for bigger values (> 65,536 or < -65,536) we have an overflow. + * @param aNoLeadingSpaceForPositiveValues - Normally each positive value has a leading space as placeholder for the minus sign. + * If we know, that values are always positive, this space can be omitted by aNoLeadingSpaceForPositiveValues == true. + * @param aNumberOfCharactersToPrint - The characters to be used for the most negative value to show. !!! MUST BE < 8, This is NOT checked!!! + * I.e. 4 => max negative value is "-999" max positive value is " 999". + * Values below 10 and -10 are displayed as floats with decimal point " 9.9" and "-9.9". + * Values below 1 and -1 are displayed as floats without 0 before decimal point " .9" and "-.9". + * If positive, there is a leading space, which improves readability if directly concatenated to another value. + * e.g. "71V1.189A" is not readable, "71V 1.18A" is as well as "71V-1.18A". + * + * Saves programming space if used more than 1 times for printing floats if used instead of myLCD.print(JKComputedData.BatteryVoltageFloat, 2); + */ +#if defined(USE_PARALLEL_LCD) +void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, + bool aNoLeadingSpaceForPositiveValues) +#else +void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, + bool aNoLeadingSpaceForPositiveValues) +#endif + { + + uint16_t tAbsValue = abs(aFloatValue); // remove sign for length computation + uint8_t tNumberOfDecimals = getNumberOfDecimalsFor16BitValues(tAbsValue); + int8_t tNumberOfDecimalPlaces = (aNumberOfCharactersToPrint - 2) - tNumberOfDecimals; + if (aNoLeadingSpaceForPositiveValues && aFloatValue >= 0) { + tNumberOfDecimalPlaces++; // Use this increased value internally, since we do not eventually print the '-' + } +#if defined(LOCAL_DEBUG) + Serial.print(F("NumberOfDecimalPlaces(")); + Serial.print(tAbsValue); + Serial.print(F(", ")); + Serial.print(aNumberOfCharactersToPrint); + Serial.print(F(")=")); + Serial.print(tNumberOfDecimalPlaces); + Serial.print(F(" NumberOfDecimals=")); + Serial.println(tNumberOfDecimals); +#endif + if (tNumberOfDecimalPlaces < 0) { + tNumberOfDecimalPlaces = 0; + } + + char tStringBuffer[9]; // For aNumberOfCharactersToPrint up to 8 + uint8_t tStartIndex = 0; + if (tNumberOfDecimals == 0 && tNumberOfDecimalPlaces > 0) { + if (aFloatValue >= 0) { + if (!aNoLeadingSpaceForPositiveValues) { + aLCD->print(' '); + } + tStartIndex = 1; + } else { + aLCD->print('-'); + tStartIndex = 2; + } + } +#if defined(__AVR__) + dtostrf(aFloatValue, aNumberOfCharactersToPrint, tNumberOfDecimalPlaces, tStringBuffer); +#else + snprintf(sStringBuffer, sizeof(tStringBuffer), "%f", aFloatValue); +#endif + aLCD->print(&tStringBuffer[tStartIndex]); +} + +#if defined(USE_PARALLEL_LCD) +void LCDTestPrintFloatValueRightAligned(LiquidCrystal *aLCD) +#else +void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD) +#endif + { + Serial.println(F("LCDTestPrintFloatValueRightAligned: 1.")); + + aLCD->clear(); + float tTestValue = 123.45; + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4); // no leading space here + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3); // no leading space here + // Result=" 123.4 123 123123" + + aLCD->setCursor(0, 1); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 6); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 5); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 4); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 3); // requires also 5 character + // Result="-123.4 -123-123-123" + + aLCD->setCursor(0, 2); + tTestValue = -1.234; + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2); + // Result="-1.234-1.23-1.2 -1-1" + + aLCD->setCursor(0, 3); + tTestValue = -0.1234; + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2); + // Result="-.1234-.123-.12-.1-0" + + delay(4000); + Serial.println(F("LCDTestPrintFloatValueRightAligned: 2.")); + + aLCD->clear(); + tTestValue = 123.45; + // no leading space here + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true); + // Result="123.45123.4 123123" + + aLCD->setCursor(0, 1); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 6, true); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 5, true); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 4, true); + LCDPrintFloatValueRightAligned(aLCD, -tTestValue, 3, true); + // Result="-123.4 -123-123-123" + + tTestValue = 1.2344; // .12345 leads to rounding up for .1235 + aLCD->setCursor(0, 2); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2, true); + // Result="1.23441.2341.231.2 1" + + tTestValue = 0.12344; // .12345 leads to rounding up for .1235 + aLCD->setCursor(0, 3); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 6, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 5, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 4, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 3, true); + LCDPrintFloatValueRightAligned(aLCD, tTestValue, 2, true); + // Result=".12344.1234.123.12.1" + + delay(4000); + Serial.println(F("LCDTestPrintFloatValueRightAligned: End")); +} + +/* + * On my 2004 LCD the custom characters are available under 0 to 7 and mirrored to 8 to 15 + * The characters 0x80 to 0x8F are blanks + */ +#if defined(USE_PARALLEL_LCD) +void LCDShowSpecialCharacters(LiquidCrystal *aLCD) +#else +void LCDShowSpecialCharacters(LiquidCrystal_I2C *aLCD) +#endif + { + aLCD->setCursor(0, 0); + // 0 to 7 are mirrored to 8 to 15 as described in datasheet + for (uint_fast8_t i = 0; i < 0x8; ++i) { + aLCD->write(i); + } + // Print some interesting characters + aLCD->write(0xA1); + aLCD->write(0xA5); + aLCD->write(0xB0); + aLCD->write(0xDB); + aLCD->write(0xDF); + + aLCD->setCursor(0, 1); + // The characters 0x10 to 0x1F seem to be all blanks => ROM Code: A00 + for (uint_fast8_t i = 0x10; i < 0x20; ++i) { + aLCD->write(i); + } + aLCD->setCursor(0, 2); + // The characters 0x80 to 0x8F seem to be all blanks => ROM Code: A00 + for (uint_fast8_t i = 0x80; i < 0x90; ++i) { + aLCD->write(i); + } + aLCD->setCursor(0, 3); + // The characters 0x90 to 0x9F seem to be all blanks => ROM Code: A00 + for (uint_fast8_t i = 0x90; i < 0xA0; ++i) { + aLCD->write(i); + } + delay(2000); +} + +#if defined(USE_PARALLEL_LCD) +void LCDShowCustomCharacters(LiquidCrystal *aLCD) +#else +void LCDShowCustomCharacters(LiquidCrystal_I2C *aLCD) +#endif + { + aLCD->setCursor(0, 0); + for (uint_fast8_t i = 0; i < 0x08; ++i) { + aLCD->write(i); + } +} + +#if defined(LOCAL_DEBUG) +#undef LOCAL_DEBUG +#endif +#endif // _LCD_PRINT_UTILS_HPP diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp index a8006400e..dd5857add 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp +++ b/examples/IRDispatcherDemo/IRCommandDispatcher.hpp @@ -46,7 +46,7 @@ #include "IRCommandDispatcher.h" -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 05ae22cd7..043caa907 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -74,7 +74,7 @@ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 907e2a641..59a1f42ca 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -353,7 +353,7 @@ void noTone(uint8_t aPinNumber){ /* * Helper macro for getting a macro definition as string */ -#if !defined(STR_HELPER) +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index d7a7a9cd8..d789cd15e 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -7,7 +7,11 @@ * If RAM is not more than 2k, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds * to save RAM space, otherwise it accepts durations up to 10 ms. * - * This decoder tries to decode a pulse distance or pulse distance width with constant period (or pulse width - not enabled yet) protocol. + * This decoder tries to decode the protocols: + * - Pulse distance with constant pulse length + * - Pulse distance width with constant period length + * - Pulse width with constant pause length - not enabled yet + * * 1. Analyze all space and mark length * 2. Decide which protocol we have * 3. Try to decode with the mark and space data found in step 1 From bb4435fd7a93aa5d0f8f2fea9f6d8c40ec2454ca Mon Sep 17 00:00:00 2001 From: ArminJo Date: Tue, 9 Dec 2025 16:56:52 +0100 Subject: [PATCH 103/133] Changed USE_DEFAULT_FEEDBACK_LED_PIN from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. Changed timer for ATtiny16X4. --- .github/workflows/LibraryBuild.yml | 7 ++++++ README.md | 3 ++- changelog.md | 4 ++++ examples/AllProtocolsOnLCD/LCDPrintUtils.hpp | 12 +++++----- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/ControlRelay/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../IRDispatcherDemo/IRDispatcherDemo.ino | 14 ++++------- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/MicroGirs/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../MultipleReceivers/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../ReceiveAndSend/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/ReceiveDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/ReceiveDemo/ReceiveDemo.ino | 4 ++-- examples/ReceiveDump/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- .../ReceiveOneAndSendMultiple.ino | 6 +++++ .../SendAndReceive/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/SendDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- .../SendProntoDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/SendRawDemo/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../SimpleReceiver/PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- .../PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/SimpleSender/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/TinyReceiver/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/TinySender/PinDefinitionsAndMore.h | 23 +++++++++++-------- examples/UnitTest/PinDefinitionsAndMore.h | 23 +++++++++++-------- src/IRFeedbackLED.hpp | 8 +++---- src/IRReceive.hpp | 2 +- src/IRremoteInt.h | 2 +- src/ir_DistanceWidthProtocol.hpp | 4 ++++ src/private/IRTimer.hpp | 5 ++-- 37 files changed, 370 insertions(+), 276 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index edc0b8758..ec870dfcb 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -73,6 +73,7 @@ jobs: - esp32:esp32:featheresp32:FlashFreq=80 - esp32:esp32:esp32c3 - esp32:esp32:lolin_s2_mini + - esp32:esp32:nano_nora - STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 - STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072 - stm32duino:STM32F1:genericSTM32F103C @@ -260,6 +261,12 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! All: -DRAW_BUFFER_LENGTH=1500 + - arduino-boards-fqbn: esp32:esp32:nano_nora + 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 # diff --git a/README.md b/README.md index ee5c72624..235bfae27 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ Any other extension would work, e.g. *cinclude*, but *hpp* seems to be common se # Using the new *.hpp files In order to support [compile options](#compile-options--macros-for-this-library) more easily, -you must use the statement `#include ` instead of `#include ` in your main program (aka *.ino file with setup() and loop()). +you **must** use the statement `#include ` instead of `#include ` in your main program (aka *.ino file with setup() and loop()). In **all other files** you must use the following, to **prevent `multiple definitions` linker errors**: @@ -1033,6 +1033,7 @@ The code for the timer and the **timer selection** is located in [private/IRTime | [ATtiny167 > 4 MHz](https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/extras/ATtiny_x7.md) | **1** | **9**, 8 - 15 | **8 - 15** | | [ATtiny1604](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x04.md) | **TCB0** | **PA05** | | [ATtiny1614, ATtiny816](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md) | **TCA0** | **PA3** | +| [ATtiny1624](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x24.md) | **TCA0** | **PA3** | | [ATtiny3217](https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x17.md) | **TCA0**, TCD | % | | [ATmega8](https://github.com/MCUdude/MiniCore#supported-microcontrollers) | **1** | **9** | | [ATmega1284](https://github.com/MCUdude/MightyCore#supported-microcontrollers) | 1, **2**, 3 | 13, 14, 6 | diff --git a/changelog.md b/changelog.md index 0da4b7061..67fdd1e22 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.6.0 +- Changed USE_DEFAULT_FEEDBACK_LED_PIN from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. +- Changed timer for ATtiny16X4. + # 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. diff --git a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp index 92a6378bb..29c4a2b54 100644 --- a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp +++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp @@ -80,7 +80,7 @@ size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue); void LCDPrintAsFloatAs5CharacterString(LiquidCrystal *aLCD, uint16_t aValueInMillivolts); void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, bool aNoLeadingSpaceForPositiveValues = false); -void LCDTestPrintFloatValueRightAligned(LiquidCrystal *aLCD); +void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD); void LCDShowSpecialCharacters(LiquidCrystal *aLCD); void LCDShowCustomCharacters(LiquidCrystal *aLCD); #else @@ -264,12 +264,12 @@ void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, } #if defined(USE_PARALLEL_LCD) -void LCDTestPrintFloatValueRightAligned(LiquidCrystal *aLCD) +void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD) #else -void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD) +void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal_I2C *aLCD) #endif { - Serial.println(F("LCDTestPrintFloatValueRightAligned: 1.")); + aSerial->println(F("LCDTestPrintFloatValueRightAligned: 1.")); aLCD->clear(); float tTestValue = 123.45; @@ -305,7 +305,7 @@ void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD) // Result="-.1234-.123-.12-.1-0" delay(4000); - Serial.println(F("LCDTestPrintFloatValueRightAligned: 2.")); + aSerial->println(F("LCDTestPrintFloatValueRightAligned: 2.")); aLCD->clear(); tTestValue = 123.45; @@ -342,7 +342,7 @@ void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD) // Result=".12344.1234.123.12.1" delay(4000); - Serial.println(F("LCDTestPrintFloatValueRightAligned: End")); + aSerial->println(F("LCDTestPrintFloatValueRightAligned: End")); } /* diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 6df3321ab..355c13148 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -127,7 +127,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRMP library version " VERSION_IRMP)); #endif -#if !defined(ESP8266) && !defined(NRF5) +#if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // play feedback tone before setup, since it kills the IR timer settings tone(TONE_PIN, 1000, 50); delay(50); @@ -233,23 +233,19 @@ void doLedBlink20times() { } void doTone1800() { -#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) +#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) && defined(TONE_PIN) irmp_tone(TONE_PIN, 1800, 200); -#else -# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266 +#elif !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone() stops timer 1 for ESP8266 tone(TONE_PIN, 1800, 200); -# endif #endif } void doTone2200() { -#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) +#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) && defined(TONE_PIN) // use IRMP compatible function for tone() irmp_tone(TONE_PIN, 2200, 50); -#else -# if !defined(ESP8266) && !defined(NRF5) // tone() stops timer 1 for ESP8266 +#elif !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone() stops timer 1 for ESP8266 tone(TONE_PIN, 2200, 50); -# endif #endif } diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 4b44fc3d8..c767b68dd 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -303,7 +303,7 @@ void loop() { * Stop receiver, generate a single beep and start receiver again */ void generateTone() { -# if !defined(ESP8266) && !defined(NRF5) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). +# if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). # if defined(ESP32) // ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too. tone(TONE_PIN, 2200, 8); # else @@ -321,7 +321,7 @@ void handleOverflow() { Serial.println(F("Try to increase the \"RAW_BUFFER_LENGTH\" value of " STR(RAW_BUFFER_LENGTH) " in " __FILE__)); // see also https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library -#if !defined(ESP8266) && !defined(NRF5) && FLASHEND >= 0x3FFF // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). +#if !defined(ESP8266) && !defined(NRF5) && FLASHEND >= 0x3FFF && defined(TONE_PIN) // tone on esp8266 works once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). /* * Stop timer, generate a double beep and start timer again */ diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index 3eb22c933..179c1be6d 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -115,7 +115,9 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE)); // tone before IR setup, since it kills the IR timer settings +#if defined(TONE_PIN) tone(TONE_PIN, 2200, 400); +#endif digitalWrite(LED_BUILTIN, HIGH); delay(400); digitalWrite(LED_BUILTIN, LOW); @@ -208,10 +210,12 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { Serial.print(tWaitTimeAfterBoot / 1000); Serial.println(F(" seconds after boot to be ready for the command")); +#if defined(TONE_PIN) tone(TONE_PIN, 2200, 100); delay(200); tone(TONE_PIN, 2200, 100); delay(100); +#endif if (millis() < tWaitTimeAfterBoot) { Serial.print(F("Now do a blocking wait for ")); @@ -222,8 +226,10 @@ void sendSamsungSmartHubMacro(bool aDoSelect) { } // Do beep feedback for special key to be received +#if defined(TONE_PIN) tone(TONE_PIN, 2200, 200); delay(200); +#endif #if !defined(ESP32) IrReceiver.restartTimer(); // Restart IR timer. diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 59a1f42ca..5c2c53c28 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -111,20 +111,23 @@ #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 +# elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 -#define IR_SEND_PIN PIN_PA3 // 10 -#define TONE_PIN PIN_PA5 // 1 -#define APPLICATION_PIN PIN_PA4 // 0 - -# elif defined(__AVR_ATtiny1604__) && 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 TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 -#define tone(...) void() // Define as void, since TCB0_INT_vect is also used by tone() -#define noTone(a) void() -#define TONE_PIN 42 // Dummy for examples using it +# elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PA4 // 0 + +# elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore +#define IR_RECEIVE_PIN PIN_PA1 // 8 +#define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 +#define TONE_PIN PIN_PA3 // 1 TCA0-WO3 +#define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index a40abdad6..77fcb59c1 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -40,15 +40,15 @@ * Contains pin number and enable status of the feedback LED */ struct FeedbackLEDControlStruct { - uint8_t FeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN; ///< if USE_DEFAULT_FEEDBACK_LED_PIN / 0, then use digitalWriteFast(LED_BUILTIN,..) otherwise use digitalWrite(FeedbackLEDPin,..) + uint8_t FeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN; ///< if USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF, 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 /** - * @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 + * @param aFeedbackLEDPin If FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF, then use digitalWrite(FeedbackLEDPin,..) + * If FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF and no LED_BUILTIN defined, disable LED feedback */ void setLEDFeedbackPin(uint8_t aFeedbackLEDPin) { FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; @@ -73,7 +73,7 @@ void disableLEDFeedback() { /** * Flash LED while receiving or sending IR data. Does not check if enabled, this must be done by the caller. - * Handles the USE_DEFAULT_FEEDBACK_LED_PIN / 0 value of FeedbackLEDPin and the macro FEEDBACK_LED_IS_ACTIVE_LOW. + * Handles the USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF 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) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 712545d53..97e81b13c 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -809,7 +809,7 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy /** * 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. + * In normal decoder, we check whether there is a timing for a 1 (usually the longer timing) within a range of 75 % to 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 diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 1c52c6afa..47a98f78e 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -222,7 +222,7 @@ struct decode_results { /** * Main class for receiving IR signals */ -#define USE_DEFAULT_FEEDBACK_LED_PIN 0 // we need it here +#define USE_DEFAULT_FEEDBACK_LED_PIN 0xFF // we need it here class IRrecv { public: diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index d789cd15e..52fbf45f3 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -231,7 +231,11 @@ 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) { +#if(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE > 0xFF) + uint16_t tDurationTicks = irparams.rawbuf[i]; +#else auto tDurationTicks = irparams.rawbuf[i]; +#endif if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) { tDurationArray[tDurationTicks]++; // count duration if less than DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE if (tIndexOfMaxDuration < tDurationTicks) { diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index bb04b0559..52162cd95 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -183,12 +183,13 @@ void disableSendPWMByTimer() { // Nano Every, Uno WiFi Rev2 and similar #elif defined(__AVR_ATmega808__) || defined(__AVR_ATmega809__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega3209__) \ - || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny1604__) + || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) # if !defined(IR_USE_AVR_TIMER_B) #define IR_USE_AVR_TIMER_B // send pin = pin 6 on ATmega4809 1 on ATmega4809 # endif -#elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards +#elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1604__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1624__) \ + || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D) #define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD //#define IR_USE_AVR_TIMER_D // use this if you use TinyCore From 429ffaa084169b9f1ee70e3c90a7fc16c3d73d9a Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 21 Dec 2025 12:37:20 +0100 Subject: [PATCH 104/133] Closes #1332 decodeSamsung() not detecting 8 bit command. --- src/IRSend.hpp | 6 +++--- src/ir_Samsung.hpp | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 121e5ca2d..35c992395 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -1207,15 +1207,15 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas 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 + tMask = 1UL << aNumberOfBits; // mask is now set for the virtual start bit before the MSB of data 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 :-). + tLastBitValue = 0; // Force to send the mark if tNextBitIsOne is 0 (which it is not the case 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 + tMask = 1UL >> 1; // adjust mask to 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 diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 46ec5d550..3945e3a79 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -337,17 +337,15 @@ bool IRrecv::decodeSamsung() { } else { /* * Samsung32 + * check if we have 8 bit command and / or 8 bit address */ if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { - // 8 bit command protocol -> assume 8 bit address + // 8 bit command decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit } if (tValue.UByte.MidLowByte == tValue.UByte.LowByte) { - decodedIRData.address = tValue.UByte.LowByte; // assume LowByte == MidLowByte as seen for a LG HX906 A/V Receive E8172C2C - } else { - // 16 bit command protocol, address is filled above with the 16 bit value - decodedIRData.command = tValue.UWord.HighWord; // first 16 bit + decodedIRData.address = tValue.UByte.LowByte; // 8 bit address as seen for a LG HX906 A/V Receive E8172C2C } decodedIRData.numberOfBits = SAMSUNG_BITS; From c26b5024676fad3750e4331292e9eb4bf5a69633 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 21 Dec 2025 19:04:44 +0100 Subject: [PATCH 105/133] Closes #1325 IrSender.begin(IR_SEND_PIN, LED) sets pinMode for IR_SEND_PIN but not for LED --- src/IRFeedbackLED.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 77fcb59c1..175546118 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -52,6 +52,11 @@ struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED contro */ void setLEDFeedbackPin(uint8_t aFeedbackLEDPin) { FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; + if (__builtin_constant_p(aFeedbackLEDPin)) { + pinModeFast(aFeedbackLEDPin, OUTPUT); + } else { + pinMode(aFeedbackLEDPin, OUTPUT); + } } /* From e64908b3f0b90a40895d44a39cf4dac92ed06a0b Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 21 Dec 2025 19:49:47 +0100 Subject: [PATCH 106/133] Housekeeping + closes #1331 - Bitmask error in sendBiphaseData() when not sending start bit --- examples/SendDemo/SendDemo.ino | 10 ++++-- examples/UnitTest/UnitTest.ino | 6 ++++ src/IRSend.hpp | 34 +++++++++---------- src/ir_RC5_RC6.hpp | 60 ++++++++++++++++++++-------------- src/ir_Samsung.hpp | 3 ++ 5 files changed, 68 insertions(+), 45 deletions(-) diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 208b1adb3..320133a33 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -380,11 +380,15 @@ void loop() { IrSender.sendSamsung(sAddress, sCommand, sRepeats); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Samsung 16 bit command")); + Serial.println(F("Send Samsung 8 bit command and 16 bit address")); Serial.flush(); - IrSender.sendSamsung(sAddress, s16BitCommand, sRepeats); + IrSender.sendSamsung16BitAddressAnd8BitCommand(sAddress, sCommand, sRepeats); delay(DELAY_AFTER_SEND); + Serial.println(F("Send Samsung 16 bit command and address")); + Serial.flush(); + IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats); + Serial.println(F("Send Samsung48 16 bit command")); Serial.flush(); IrSender.sendSamsung48(sAddress, s16BitCommand, sRepeats); @@ -402,7 +406,7 @@ void loop() { 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); + IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sCommandExtension, sRepeats); delay(DELAY_AFTER_SEND); Serial.println(F("Send Marantz variant of RC5x with 7 command bits and additional command extension")); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index d9049d2da..2cf864e79 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -841,6 +841,12 @@ void loop() { checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); + Serial.println(F("Send Samsung 8 bit command and 16 bit address")); + Serial.flush(); + IrSender.sendSamsung16BitAddressAnd8BitCommand(sAddress, sCommand, sRepeats); + checkReceive(sAddress, sCommand); + delay(DELAY_AFTER_SEND); + Serial.println(F("Send Samsung 16 bit command and address")); Serial.flush(); IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats); diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 35c992395..9e467d471 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -115,7 +115,7 @@ 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 aFeedbackLEDPin If 0 / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions + * @param aFeedbackLEDPin If 0xFF / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions */ void IRsend::begin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin) { #if defined(IR_SEND_PIN) @@ -1200,25 +1200,23 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas #endif // Data - Biphase code MSB first -// prepare for start with sending the start bit, which is 1 - 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 before the MSB of data + uint8_t tBitsToSend = aNumberOfBits; // total number of bits to send including start bit if specified + if (aSendStartBit) { + tBitsToSend++; // +1 for additional start bit + } + uint32_t tMask = 1UL << (tBitsToSend - 1); // Mask is now set to the the MSB of data or the virtual start bit before the MSB of data + + bool tLastBitWasOne; + bool tNextBitIsOne; 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 the case here). Does not increase code size :-). + tNextBitIsOne = true; // Start bit is a 1, value is copied to tCurrentBitIsOne + tLastBitWasOne = false; // Force to send the mark if tNextBitIsOne is 0 (which it is not the case 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; // adjust mask to 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 + tLastBitWasOne = false; // Force to send the mark if tNextBitIsOne is 0 } // now send all bits @@ -1237,17 +1235,17 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas // if next bit is 0, extend the current mark in order to generate a continuous signal without short breaks mark(2 * aBiphaseTimeUnit); } - tLastBitValue = 1; + tLastBitWasOne = true; } else { #if defined(LOCAL_TRACE) Serial.print('0'); #endif - if (tLastBitValue == 0) { - mark(aBiphaseTimeUnit); // if next bit is 1 send a single mark + if (!tLastBitWasOne) { + mark(aBiphaseTimeUnit); // if last bit was 0 send a single mark } space(aBiphaseTimeUnit); - tLastBitValue = 0; + tLastBitWasOne = false; } } IR_TRACE_PRINTLN(); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 94cc20f98..65d87dcb2 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -59,7 +59,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 +1800 Sum: 23100 - RC5X with 7.th MSB of command set + RC5X with 7.th MSB of command set as 1 Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first +1800,-1750 + 850,- 900 +1800,- 850 + 950,- 850 + 900,-1750 @@ -101,28 +101,34 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 ************************************/ /** + * !!! Not tested, because no Marantz remote was at hand and no receive function was contributed!!! * @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X. * @param aMarantzExtension 6 bit command extension which is sent after aCommand. aCommand and aMarantzExtension are sent after a short pause. * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. */ -void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats, - bool aEnableAutomaticToggle) { +void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats, + bool aEnableAutomaticToggle) { - // Set IR carrier frequency + // Set IR carrier frequency enableIROut (RC5_RC6_KHZ); uint16_t tIRData = (aAddress & 0x1F); - if (aCommand < 0x40) { - // Auto discovery of RC5X, set field bit to 1 - tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); - } else { - // Mask bit 7 of command and let field bit 0 + /* + * Process field bit (the bit after start bit) + * Field bit is 1 for RC5 and 0 (inverted 7. command bit) for RC5X + */ + if (aCommand >= 0x40) { // Auto discovery of RC5X + // Mask bit 7 of command to set field bit to 0 (inverted 1) for RC5X aCommand &= 0x3F; + } else { + // Set field bit to 1 for RC5 + tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); // 1 << 6 = 0x40 } - // Set the command to the 2nd part of data to be sent after the pause + + // Set the command to the 2nd part of data to be sent after the pause uint16_t tIRExtData = (aCommand << RC5_EXTENSION_BITS); - // Set the Marantz command extension bits + // Set the Marantz command extension bits tIRExtData |= (aMarantzExtension & 0x3F); if (aEnableAutomaticToggle) { @@ -160,17 +166,21 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarant */ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) { - // Set IR carrier frequency + // Set IR carrier frequency enableIROut (RC5_RC6_KHZ); - uint16_t tIRData = ((aAddress & 0x1F) << (RC5_COMMAND_BITS)); + uint16_t tIRData = ((aAddress & 0x1F) << (RC5_COMMAND_BITS)); // << 6 - if (aCommand < 0x40) { - // Auto discovery of RC5X, set field bit to 1 - tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS); - } else { - // Mask bit 7 of command and let field bit 0 + /* + * Process field bit (the bit after start bit) + * Field bit is 1 for RC5 and 0 (inverted 7. command bit) for RC5X + */ + if (aCommand >= 0x40) { // Auto discovery of RC5X + // Mask bit 7 of command to set field bit to 0 (inverted 1) for RC5X aCommand &= 0x3F; + } else { + // Set field bit to 1 for RC5 + tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS); // 1 << 12 = 0x1000 } tIRData |= aCommand; @@ -201,14 +211,17 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe /** * Try to decode data as RC5 protocol + * mark->space => 0 + * space->mark => 1 * _ _ _ _ _ _ _ _ _ _ _ _ _ * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of each data bit period - * _ _ - Mark - * 2 Start bits for RC5 _____| |_| ... - Data starts with a space->mark bit - * - Space + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ sample point for bit value + * _ _ + * 2 Start bits for RC5 _____| |_| ..|...|.. + * * _ - * 1 Start bit for RC5X _____| ... + * 1 Start bit for RC5X _____| ..|...|...|.. * */ bool IRrecv::decodeRC5() { @@ -517,8 +530,7 @@ bool IRrecv::decodeRC6() { } // Check header "mark" and "space", this must be done for repeat and data - if (!matchMark(irparams.rawbuf[1], RC6_HEADER_MARK) - || !matchSpace(irparams.rawbuf[2], RC6_HEADER_SPACE)) { + if (!matchMark(irparams.rawbuf[1], RC6_HEADER_MARK) || !matchSpace(irparams.rawbuf[2], RC6_HEADER_SPACE)) { // no debug output, since this check is mainly to determine the received protocol IR_DEBUG_PRINT(F("RC6: ")); IR_DEBUG_PRINTLN(F("Header mark or space length is wrong")); diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 3945e3a79..82fb94adc 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -342,6 +342,9 @@ bool IRrecv::decodeSamsung() { if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { // 8 bit command decodedIRData.command = tValue.UByte.MidHighByte; // first 8 bit + } else { + // 16 bit command + decodedIRData.command = tValue.UWord.HighWord; } if (tValue.UByte.MidLowByte == tValue.UByte.LowByte) { From 231255ce6f4dad51b5ff8b0066ddf56fd80a4077 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 22 Dec 2025 09:58:50 +0100 Subject: [PATCH 107/133] Closes #1333 / 1325 - set Feedback LED pin to output --- .../MultipleReceivers/MultipleReceivers.ino | 2 +- src/IRFeedbackLED.hpp | 17 +++++++++++++---- src/IRReceive.hpp | 10 +++++----- src/IRSend.hpp | 6 +++--- src/IRVersion.h | 4 ++-- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index 254db7e1e..24c7495ef 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -60,7 +60,7 @@ //#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 +void UserIRReceiveTimerInterruptHandler(); // Is defined below and must be declared 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 diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 175546118..5efbc5f6c 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -47,15 +47,24 @@ struct FeedbackLEDControlStruct { struct FeedbackLEDControlStruct FeedbackLEDControl; ///< The feedback LED control instance /** - * @param aFeedbackLEDPin If FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF, then use digitalWrite(FeedbackLEDPin,..) + * @param aFeedbackLEDPin If FeedbackLEDPin != USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF, then use digitalWrite / digitalWriteFast(FeedbackLEDPin,..) + * If FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF and LED_BUILTIN defined, then use digitalWriteFast(LED_BUILTIN,..) * If FeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF and no LED_BUILTIN defined, disable LED feedback */ void setLEDFeedbackPin(uint8_t aFeedbackLEDPin) { FeedbackLEDControl.FeedbackLEDPin = aFeedbackLEDPin; - if (__builtin_constant_p(aFeedbackLEDPin)) { - pinModeFast(aFeedbackLEDPin, OUTPUT); + + // use fast macros here + if (aFeedbackLEDPin == USE_DEFAULT_FEEDBACK_LED_PIN) { +#if defined(LED_BUILTIN) + pinModeFast(LED_BUILTIN, OUTPUT); +#endif } else { - pinMode(aFeedbackLEDPin, OUTPUT); + if (__builtin_constant_p(aFeedbackLEDPin)) { + pinModeFast(aFeedbackLEDPin, OUTPUT); + } else { + pinMode(aFeedbackLEDPin, OUTPUT); + } } } diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 97e81b13c..96e105309 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -83,7 +83,7 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin) { /** * Instantiate the IRrecv class. Multiple instantiation is not supported. * @param aReceivePin Arduino pin to use, where a demodulating IR receiver is connected. - * @param aFeedbackLEDPin if 0, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions + * @param aFeedbackLEDPin if 0xFF, then take board specific LED_BUILTIN pin if it is defined as macro */ IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) { setReceivePin(aReceivePin); @@ -310,7 +310,7 @@ ISR() * Initializes the receive and feedback pin * @param aReceivePin The Arduino pin number, where a demodulating IR receiver is connected. * @param aEnableLEDFeedback if true / ENABLE_LED_FEEDBACK, then let the feedback led blink on receiving IR signal - * @param aFeedbackLEDPin if 0 / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions + * @param aFeedbackLEDPin if 0xFF, then take board specific LED_BUILTIN pin if it is defined as macro */ void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) { @@ -1203,7 +1203,7 @@ uint_fast8_t IRrecv::getBiphaselevel() { /** * Compare two (tick) values for Hash decoder - * Use a tolerance of 20% to enable e.g. 500 and 600 (NEC timing) to be equal + * Use a tolerance of 20% to enable e.g. 500 and 600 (NEC timing) and at least 200 and 250 to be equal * @return 0 if newval is shorter, 1 if newval is equal, and 2 if newval is longer */ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) { @@ -1222,7 +1222,7 @@ uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) { * (e.g. Sony, NEC, RC5), the code is hashed to a 32-bit value. * * 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. + * is more than 20% shorter (0), the same (+/- 20%) length (1), or more than 20% longer (2) than the previous MARK or SPACE. * 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. * @@ -1247,7 +1247,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(irparams.rawbuf[i], irparams.rawbuf[i + 2]); - // Add value into the hash + // Add value into the hash - (0 if rawbuf[i + 2] is more than 20 % shorter, 1 if rawbuf[i + 2] is equal, and 2 if rawbuf[i + 2] is longer than rawbuf[i]) hash = (hash * FNV_PRIME_32) ^ value; } diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 9e467d471..5dfac2bbf 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -89,7 +89,7 @@ void IRsend::begin(){ /** * 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 + * @param aFeedbackLEDPin If USE_DEFAULT_FEEDBACK_LED_PIN / 0xFF, then take board specific LED_BUILTIN pin if it is defined as macro */ void IRsend::begin(uint_fast8_t aFeedbackLEDPin) { setLEDFeedbackPin(aFeedbackLEDPin); @@ -101,7 +101,7 @@ IRsend::IRsend(uint_fast8_t aSendPin) { // @suppress("Class members should be pr } /** - * Initializes the send pin and enable LED feedback with board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions + * Initializes the send pin and enable LED feedback with board specific LED_BUILTIN pin if it is defined as macro * @param aSendPin The Arduino pin number, where a IR sender diode is connected. */ void IRsend::begin(uint_fast8_t aSendPin) { @@ -115,7 +115,7 @@ 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 aFeedbackLEDPin If 0xFF / USE_DEFAULT_FEEDBACK_LED_PIN, then take board specific FEEDBACK_LED_ON() and FEEDBACK_LED_OFF() functions + * @param aFeedbackLEDPin If 0xFF, then take board specific LED_BUILTIN pin if it is defined as macro */ void IRsend::begin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin) { #if defined(IR_SEND_PIN) diff --git a/src/IRVersion.h b/src/IRVersion.h index 24890fc3f..ebdc8f770 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,9 +36,9 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.5.0" +#define VERSION_IRREMOTE "4.6.0" #define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 5 +#define VERSION_IRREMOTE_MINOR 6 #define VERSION_IRREMOTE_PATCH 0 /* From 15dc3e84dbb8705f8c9137e79826371deb90951a Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 4 Jan 2026 23:24:51 +0100 Subject: [PATCH 108/133] Bumped version to 4.6.0 --- .github/workflows/LibraryBuild.yml | 22 ++++----- changelog.md | 3 ++ examples/AllProtocolsOnLCD/LCDPrintUtils.hpp | 51 +++++++++----------- examples/ReceiveDemo/ReceiveDemo.ino | 2 +- library.json | 2 +- library.properties | 2 +- src/ir_Samsung.hpp | 3 +- 7 files changed, 43 insertions(+), 42 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index ec870dfcb..415811bd8 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -67,8 +67,8 @@ jobs: # - 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 - - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal +# - 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 @@ -188,15 +188,15 @@ jobs: # # megaTinyCore # - - 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 +# - 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 diff --git a/changelog.md b/changelog.md index 67fdd1e22..058221fc5 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,9 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.6.0 - Changed USE_DEFAULT_FEEDBACK_LED_PIN from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. - Changed timer for ATtiny16X4. +- Fixed missing initialization with pinMode() for feedback LED. +- Fixed bitmask error in sendBiphaseData() when not sending start bit. +- Improved decodeSamsung(). # 4.5.0 - Added support for multiple receiver instances. diff --git a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp index 29c4a2b54..f113f0e85 100644 --- a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp +++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp @@ -40,24 +40,18 @@ #if defined(USE_PARALLEL_2004_LCD) || defined(USE_PARALLEL_1602_LCD) #define USE_PARALLEL_LCD -# if defined(USE_PARALLEL_2004_LCD) -#define LCD_COLUMNS 20 -#define LCD_ROWS 4 -# else -#define LCD_COLUMNS 16 -#define LCD_ROWS 2 -# endif #include "LiquidCrystal.h" #else #define USE_SERIAL_LCD -# if defined(USE_SERIAL_2004_LCD) -#define LCD_COLUMNS 20 -#define LCD_ROWS 4 -# else +#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster +#endif + +#if defined(USE_PARALLEL_1602_LCD) || defined(USE_SERIAL_1602_LCD) #define LCD_COLUMNS 16 #define LCD_ROWS 2 -# endif -#include "LiquidCrystal_I2C.hpp" // Here we use an enhanced version, which supports SoftI2CMaster +#else +#define LCD_COLUMNS 20 +#define LCD_ROWS 4 #endif /* @@ -75,12 +69,12 @@ extern char sStringBuffer[]; // For rendering a LCD row with snprintf_P() #if defined(USE_PARALLEL_LCD) void LCDResetCursor(LiquidCrystal *aLCD); void LCDPrintSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint); -void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber); +void LCDClearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber); // Cursor is a start of line size_t LCDPrintHex(LiquidCrystal *aLCD, uint16_t aHexByteValue); -void LCDPrintAsFloatAs5CharacterString(LiquidCrystal *aLCD, uint16_t aValueInMillivolts); +void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal *aLCD, uint16_t aValueInMilliUnits); void LCDPrintFloatValueRightAligned(LiquidCrystal *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, bool aNoLeadingSpaceForPositiveValues = false); -void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD); +void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD); void LCDShowSpecialCharacters(LiquidCrystal *aLCD); void LCDShowCustomCharacters(LiquidCrystal *aLCD); #else @@ -88,7 +82,7 @@ void LCDResetCursor(LiquidCrystal_I2C *aLCD); void LCDPrintSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint); void LCDClearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber); size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue); -void LCDPrintAsFloatAs5CharacterString(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts); +void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts); void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, uint8_t aNumberOfCharactersToPrint, bool aNoLeadingSpaceForPositiveValues = false); void LCDTestPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD); @@ -151,15 +145,15 @@ size_t LCDPrintHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue) * Use 2 decimals, if value is >= 10 */ #if defined(USE_PARALLEL_LCD) -void LCDPrintAsFloatAs5CharacterString(LiquidCrystal *aLCD, uint16_t aValueInMillivolts) +void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal *aLCD, uint16_t aValueInMilliUnits) #else -void LCDPrintAsFloatAs5CharacterString(LiquidCrystal_I2C *aLCD, uint16_t aValueInMillivolts) +void LCDPrintAsFloatAs5CharacterString_2_3_Decimals(LiquidCrystal_I2C *aLCD, uint16_t aValueInMilliUnits) #endif { - if (aValueInMillivolts < 10000) { - aLCD->print(((float) (aValueInMillivolts)) / 1000, 3); + if (aValueInMilliUnits < 10000) { + aLCD->print(((float) (aValueInMilliUnits)) / 1000, 3); } else { - aLCD->print(((float) (aValueInMillivolts)) / 1000, 2); + aLCD->print(((float) (aValueInMilliUnits)) / 1000, 2); } } @@ -222,8 +216,7 @@ void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, #endif { - uint16_t tAbsValue = abs(aFloatValue); // remove sign for length computation - uint8_t tNumberOfDecimals = getNumberOfDecimalsFor16BitValues(tAbsValue); + uint8_t tNumberOfDecimals = getNumberOfDecimalsFor16BitValues(abs(aFloatValue)); // remove sign for length computation int8_t tNumberOfDecimalPlaces = (aNumberOfCharactersToPrint - 2) - tNumberOfDecimals; if (aNoLeadingSpaceForPositiveValues && aFloatValue >= 0) { tNumberOfDecimalPlaces++; // Use this increased value internally, since we do not eventually print the '-' @@ -262,11 +255,15 @@ void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, #endif aLCD->print(&tStringBuffer[tStartIndex]); } - +/** + * Unit test for LCDPrintFloatValueRightAligned() + * @param aSerial + * @param aLCD + */ #if defined(USE_PARALLEL_LCD) -void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD) +void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal *aLCD) #else -void LCDTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal_I2C *aLCD) +void LCDUnitTestPrintFloatValueRightAligned(Print *aSerial, LiquidCrystal_I2C *aLCD) #endif { aSerial->println(F("LCDTestPrintFloatValueRightAligned: 1.")); diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index c767b68dd..43d228708 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -244,7 +244,7 @@ void loop() { } 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.print(F("Raw data from hash decoder is 0x")); Serial.println(tDecodedRawData); } else { diff --git a/library.json b/library.json index 7aecaa48c..18db09a0b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.5.0", + "version": "4.6.0", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index ec368ba68..22a7127f9 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.5.0 +version=4.6.0 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 82fb94adc..adf77450f 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -61,6 +61,7 @@ + 600,- 550 + 600,- 550 + 550,- 550 + 600,-1650 + 550 Sum: 68750 + * Values are like NEC except SAMSUNG_HEADER_MARK (4500 instead of 9000) */ /* * Samsung repeat frame can be the original frame again or a special short repeat frame, @@ -88,7 +89,7 @@ #define SAMSUNG_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND16_BITS) #define SAMSUNG48_BITS (SAMSUNG_ADDRESS_BITS + SAMSUNG_COMMAND32_BITS) -// except SAMSUNG_HEADER_MARK, values are like NEC +// Values are like NEC except SAMSUNG_HEADER_MARK (4500 instead of 9000) #define SAMSUNG_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0 #define SAMSUNG_HEADER_MARK (8 * SAMSUNG_UNIT) // 4500 | 180 periods #define SAMSUNG_HEADER_SPACE (8 * SAMSUNG_UNIT) // 4500 From 5d63af3944e4e1d6e7c04a2762b1ddb97f0f017e Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 5 Jan 2026 10:40:19 +0100 Subject: [PATCH 109/133] Closes #1336 --- .github/workflows/LibraryBuild.yml | 34 +++++++++++----------- examples/ReceiveAndSend/ReceiveAndSend.ino | 4 +-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 415811bd8..b06c3e98f 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -62,8 +62,8 @@ jobs: - arduino:mbed:nano33ble - arduino:mbed_rp2040:pico - rp2040:rp2040:arduino_nano_connect -# - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=16pll -# - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + - ATTinyCore:avr: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 @@ -201,28 +201,28 @@ jobs: # # 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,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:attinyx5micr:LTO=enable,sketchclock=16pll + platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_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:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled + platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_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 +# SimpleSender: -DSEND_PWM_BY_TIMER +# SimpleReceiver: -DDECODE_NEC # # MegaCore diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index a104f9106..bdc61d1ea 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -23,7 +23,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2009-2025 Ken Shirriff, Armin Joachimsmeyer + * Copyright (c) 2009-2026 Ken Shirriff, Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -104,7 +104,7 @@ struct storedIRDataStruct { IRData receivedIRData; // extensions for sendRaw uint8_t rawCode[RAW_BUFFER_LENGTH]; // The durations if raw - uint8_t rawCodeLength; // The length of the code + uint16_t rawCodeLength; // The length of the code } sStoredIRData; bool sSendButtonWasActive; From 87e8e533a3fd4b13be8699a1a16d85c5b7413f58 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 25 Jan 2026 01:29:37 +0100 Subject: [PATCH 110/133] Documentation --- .github/workflows/LibraryBuild.yml | 25 ++++--- README.md | 65 ++++++++++--------- examples/AllProtocolsOnLCD/ADCUtils.hpp | 7 +- examples/AllProtocolsOnLCD/LCDPrintUtils.hpp | 6 +- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 4 ++ examples/ControlRelay/PinDefinitionsAndMore.h | 4 ++ .../IRDispatcherDemo/IRDispatcherDemo.ino | 6 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ examples/MicroGirs/PinDefinitionsAndMore.h | 4 ++ .../MultipleReceivers/PinDefinitionsAndMore.h | 4 ++ .../ReceiveAndSend/PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ examples/ReceiveDemo/PinDefinitionsAndMore.h | 4 ++ examples/ReceiveDump/PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ .../ReceiverTimingAnalysis.ino | 6 +- .../SendAndReceive/PinDefinitionsAndMore.h | 4 ++ .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 4 ++ examples/SendDemo/PinDefinitionsAndMore.h | 4 ++ examples/SendDemo/SendDemo.ino | 3 +- .../PinDefinitionsAndMore.h | 4 ++ .../SendProntoDemo/PinDefinitionsAndMore.h | 4 ++ examples/SendRawDemo/PinDefinitionsAndMore.h | 4 ++ .../SimpleReceiver/PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ .../PinDefinitionsAndMore.h | 4 ++ examples/SimpleSender/PinDefinitionsAndMore.h | 4 ++ examples/TinyReceiver/PinDefinitionsAndMore.h | 4 ++ examples/TinySender/PinDefinitionsAndMore.h | 4 ++ examples/UnitTest/PinDefinitionsAndMore.h | 4 ++ src/IRReceive.hpp | 3 +- src/IRSend.hpp | 2 +- src/IRremote.hpp | 11 +++- src/TinyIRReceiver.hpp | 2 +- 36 files changed, 180 insertions(+), 56 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index b06c3e98f..4a9e5ef01 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -64,7 +64,7 @@ jobs: - 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: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 @@ -72,6 +72,7 @@ jobs: - esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80 - esp32:esp32:featheresp32:FlashFreq=80 - esp32:esp32:esp32c3 + - esp32:esp32:esp32s3 - esp32:esp32:lolin_s2_mini - esp32:esp32:nano_nora - STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 @@ -216,13 +217,13 @@ jobs: 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 + - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled # ATtiny88 China clone board @16 MHz + platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_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 @@ -247,7 +248,7 @@ jobs: 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 + All: -DRAW_BUFFER_LENGTH=1500 -DDEBUG -DTRACE - arduino-boards-fqbn: esp32:esp32:esp32c3 platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json @@ -255,6 +256,12 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! All: -DRAW_BUFFER_LENGTH=1500 + - arduino-boards-fqbn: esp32:esp32:esp32s3 + 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 -DDEBUG + - 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))' diff --git a/README.md b/README.md index 235bfae27..0e814e8ca 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@
# Arduino IRremote -A library enabling the sending & receiving of infra-red signals. +A library enabling the sending & receiving of infrared signals. [![Badge License: MIT](https://img.shields.io/badge/License-MIT-ac8b11.svg?style=for-the-badge&labelColor=yellow)](https://opensource.org/licenses/MIT)     @@ -30,10 +30,10 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
-# Table of content +# Table of contents - [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) -- [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) +- [Common issues when using IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-issues-when-using-irremote) +- [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#migrating-legacy-projects-to-the-latest-version) * [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) @@ -41,7 +41,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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 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) +- [Why *.hpp instead of *.cpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp-files) - [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files) - [Tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tutorials) - [3 ways to specify an IR code](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#3-ways-to-specify-an-ir-code) @@ -49,7 +49,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [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) - * [RAM usage of different protocolsl](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ram-usage-of-different-protocols) + * [RAM usage of different protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ram-usage-of-different-protocols) * [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols) * [Disclaimer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#disclaimer) * [Other libraries, which may cover these protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#other-libraries-which-may-cover-these-protocols) @@ -99,15 +99,15 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr
# Supported IR Protocols -` NEC / Onkyo / Apple `     ` Denon / Sharp `     ` Panasonic / Kaseikyo ` +` NEC / Onkyo / Apple `,     ` Denon / Sharp `,     ` Panasonic / Kaseikyo `, -` JVC `     ` LG `     ` RC5 `     ` RC6 `     ` Samsung `     ` Sony `     ` Marantz ` +` JVC `,     ` LG `,     ` RC5 `,     ` RC6 `,     ` Samsung `,     ` Sony `,     ` Marantz ` -` Universal Pulse Distance `     ` Universal Pulse Width `     ` Universal Pulse Distance Width` +` Universal Pulse Distance `,     ` Universal Pulse Width `,     ` Universal Pulse Distance Width` -` Hash `     ` Pronto ` +` Hash `,     ` Pronto ` -` BoseWave `     ` Bang & Olufsen `     ` Lego `     ` FAST `     ` Whynter `     ` MagiQuest `     ` Velux ` +` 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): @@ -118,15 +118,16 @@ Protocols can be switched off and on by defining macros before the line `#includ ```
-# 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)"*.
+# Common issues when using IRremote +Or *"I build a gadget with 2 motors controlled by IR and the [IR stops after the first motor command](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor)"*.
This is due to the fact, that the motor control by AnalogWrite() uses the same timer as IR receiving.
See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) for the list of timers and pins. -# 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. +# Migrating legacy projects to the latest version +This library has been refactored, breaking backward compatibility with the old version, on which many examples on the Internet are based.
+If your code uses `irrecv.decode(&results)`, it is written for Version 2.x. This library (Version 4.x) now uses a simpler `IrReceiver.decode()` syntax. See the Conversion guide below. -## New features of version 4.5 +## New features and changes in 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`. @@ -147,19 +148,19 @@ Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.ra ### 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()`. +- The parameter `bool hasStopBit` is no longer required and removed e.g. for function `sendPulseDistanceWidth()`. ## 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). +- An 8/16 bit ****command** value as well as a 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/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. +- Allows for the generation of non-PWM signal to just **simulate an active low receiver signal** for direct connect to existing receiving devices without using IR. - Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
Reduces memory footprint and decreases decoding time. - Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**. @@ -292,7 +293,7 @@ Most likely your code will run and you will not miss the new features.
## Staying on 2.x -Consider using the [original 2.4 release form 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) +Consider using the [original 2.4 release from 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
It may be sufficient and deals flawlessly with 32 bit IR codes.
If this doesn't work for you, you can be sure that 4.x is trying to be compatible with earlier versions, so your old examples should work just fine. @@ -306,7 +307,7 @@ If this doesn't work for you, you can be sure that 4.x is trying to be compatibl
-# Why *.hpp instead of *.cpp? +# Why *.hpp instead of *.cpp files? **Every \*.cpp file is compiled separately** by a call of the compiler exclusively for this cpp file. These calls are managed by the IDE / make system. In the Arduino IDE the calls are executed when you click on *Verify* or *Upload*. @@ -351,6 +352,9 @@ The following macros will definitely be overridden with default values otherwise # 3 ways to specify an IR code There are 3 different ways of specifying a particular IR code. +- **Timing (Raw):** Records the exact duration of pulses. Uses the most memory but works for everything. +- **Encoding Schemes:** General rules for each data bit (like how 1s and 0s are shaped). +- **Protocols (Recommended):** Uses predefined names (like NEC or Sony) and small 8 or 16-bit addresses and commands. Most efficient and easiest to read. ## 1. Timing The timing of each mark/pulse and space/distance_between_pulses is specified in a list or array. @@ -361,8 +365,8 @@ For IRremote you can use a 50 µs resolution which halves the memory requir For receiving purposes you can use the **hash of the timing** provided by the `decodeHash()` decoder. ## 2. Encoding schemes -There are 3 main encoding schemes which encodes a binary bitstream / hex value: -1. `PULSE_DISTANCE`. The distance between pulses determines the bit value. This requires always a stop bit! +There are 3 main encoding schemes which encode a binary bitstream / hex value: +1. `PULSE_DISTANCE`. The distance between pulses determines the bit value. This always requires a stop bit! Examples are NEC and KASEIKYO protocols. The pulse width is constant for most protocols. 2. `PULSE_WIDTH`. The width of a pulse determines the bit value, pulse distance is constant. This requires no stop bit! The only known example is the SONY protocol. @@ -429,7 +433,7 @@ Check it with e.g. `if(IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT)` | Flag name | Description | |:---|----| -| IRDATA_FLAGS_IS_REPEAT | The gap between the preceding frame is as smaller than the maximum gap expected for a repeat. !!!We do not check for changed command or address, because it is almost not possible to press 2 different buttons on the remote within around 100 ms!!! +| IRDATA_FLAGS_IS_REPEAT | The gap between the preceding frame is as smaller than the maximum gap expected for a repeat. !!!We do not check for changed command or address, because it is virtually impossible to press 2 different buttons on the remote within around 100 ms!!! | IRDATA_FLAGS_IS_AUTO_REPEAT | The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided. Only specified for protocols DENON, and LEGO. | | IRDATA_FLAGS_PARITY_FAILED | The current (autorepeat) frame violated parity check. | | IRDATA_FLAGS_TOGGLE_BIT | Is set if RC5 or RC6 toggle bit is set. | @@ -736,12 +740,15 @@ 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 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). +Whether you use the Adafruit Neopixel library, or FastLED, interrupts get disabled on many lower end CPUs like the basic Arduinos for longer than 50 µs.
+In turn, this stops the IR interrupt handler from sampling the IR signal. + +Each WS2812 LED requires 30 µs at **800 kHz**, an **8 pixel** strip requires 240 µs and therefore **skips 4 samples** of the IR signal, which is sampled each 50 µs.
+For example, the standard timing for the NEC protocol is 560 µs or 11 samples. However, with a loss of four samples, however, we **exceed the accepted 25 %** decoding deviation threshold. One **workaround** is to wait for the IR receiver to be idle before you send the Neopixel data with `if (IrReceiver.isIdle()) { strip.show();}`.
-This **prevents at least breaking a running IR transmission** and -depending of the update rate of the Neopixel- may work quite well.
-There are some other solutions to this on more powerful processors, +This **prevents a running IR transmission from beeing broken**, and depending on the update rate of the Neopixel, it may work quite well.
+There are some other solutions to this on **more powerful CPU's**, [see this page from Marc MERLIN](http://marc.merlins.org/perso/arduino/post_2017-04-03_Arduino-328P-Uno-Teensy3_1-ESP8266-ESP32-IR-and-Neopixels.html) ## Does not work/compile with another library @@ -789,7 +796,7 @@ And because **generating a 455 kHz PWM signal is currently only implemented for For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L44). # Examples for this library -The examples are available at File > Examples > Examples from Custom Libraries / IRremote.
+These examples can be found in the Arduino IDE under File > Examples > Examples from Custom Libraries / IRremote.
**In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.**
See also [DroneBot Workshop SimpleReceiver](https://dronebotworkshop.com/ir-remotes/#SimpleReceiver_Example_Code) and [SimpleSender](https://dronebotworkshop.com/ir-remotes/#SimpleSender_Example_Code). diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index e7a2124c0..36ac867d3 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -29,7 +29,8 @@ #if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected #define ADC_UTILS_ARE_INCLUDED -#if !defined(STR) +// Helper macro for getting a macro definition as string +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif @@ -694,7 +695,7 @@ bool isVCCUSBPowered(Print *aSerial) { } /* - * It checks every 10 seconds for 6 times, and then returns true if the undervoltage condition ( <3.4V ) still applies. + * It checks every 10 seconds for 6 times, and then returns once true if the undervoltage condition ( <3.4V ) still applies. * @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown */ bool isVCCUndervoltageMultipleTimes() { @@ -732,7 +733,7 @@ bool isVCCUndervoltageMultipleTimes() { sVCCTooLowCounter++; # if defined(LOCAL_INFO) Serial.print(sVCCVoltageMillivolt); - Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV undervoltage detected: ")); + Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV -> undervoltage detected: ")); Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter); Serial.println(F(" attempts left")); diff --git a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp index f113f0e85..a4736bd10 100644 --- a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp +++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp @@ -54,9 +54,7 @@ #define LCD_ROWS 4 #endif -/* - * Helper macro for getting a macro definition as string - */ +// Helper macro for getting a macro definition as string #if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) @@ -223,7 +221,7 @@ void LCDPrintFloatValueRightAligned(LiquidCrystal_I2C *aLCD, float aFloatValue, } #if defined(LOCAL_DEBUG) Serial.print(F("NumberOfDecimalPlaces(")); - Serial.print(tAbsValue); + Serial.print(tNumberOfDecimals); Serial.print(F(", ")); Serial.print(aNumberOfCharactersToPrint); Serial.print(F(")=")); diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 355c13148..b64086ecb 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -100,11 +100,11 @@ void doTone2200(); #include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown". #include "IRCommandDispatcher.hpp" -/* - * Helper macro for getting a macro definition as string - */ +// Helper macro for getting a macro definition as string +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) +#endif void setup() { pinMode(LED_BUILTIN, OUTPUT); diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index ab732bcd0..8f9fb53d5 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -36,11 +36,11 @@ #define IR_RECEIVE_PIN 2 //#define IR_RECEIVE_PIN 3 -/* - * Helper macro for getting a macro definition as string - */ +// Helper macro for getting a macro definition as string +#if !defined(STR_HELPER) && !defined(STR) #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) +#endif #if !(defined(EICRA) && defined(EIFR) && defined(EIMSK)) void measureTimingISR(void); diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 320133a33..1d16d4cbf 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -172,8 +172,9 @@ void loop() { delay(DELAY_AFTER_SEND); if (sRepeats == 0) { -#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. +#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 */ diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 5c2c53c28..efb3b6f3f 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -353,6 +353,10 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif +#if !defined (RAMEND) +#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#endif + /* * Helper macro for getting a macro definition as string */ diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 96e105309..de05bdf3e 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1343,6 +1343,7 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTick /** * Match function WITHOUT compensating for marks exceeded or spaces shortened by demodulator hardware + * Match is true, if signal value is bigger/equal 75% and less/equal 125% of match value. * @return true, if values match */ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { @@ -1522,7 +1523,7 @@ bool IRrecv::checkForRecordGapsMicros(Print *aSerial) { aSerial->print(decodedIRData.initialGapTicks * MICROS_PER_TICK); aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of ")); aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD); - aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc..")); + aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC5 etc..")); aSerial->println(F("But it can be OK for some yet unsupported protocols, and especially for repeats.")); aSerial->println(F("If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h.")); aSerial->println(); diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 5dfac2bbf..a86966174 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -648,7 +648,7 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp * 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))) { + if ((!(aFlags & SUPPRESS_STOP_BIT)) && (uintDifferenceAbs(aOneSpaceMicros, aZeroSpaceMicros) > (aOneSpaceMicros / 4))) { // Send stop bit here #if defined(LOCAL_TRACE) Serial.print('S'); diff --git a/src/IRremote.hpp b/src/IRremote.hpp index b84963e6f..07a3e616b 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -79,6 +79,12 @@ //#define DEBUG // Activate this for lots of lovely debug output from the IRremote core. +// Helper macro for getting a macro definition as string +#if !defined(STR_HELPER) && !defined(STR) +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#endif + /**************************************************** * RECEIVING ****************************************************/ @@ -199,7 +205,6 @@ #define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code #endif - /** * microseconds per clock interrupt tick */ @@ -258,6 +263,10 @@ void disableLEDFeedback() {}; // dummy function for examples #if !defined(DISABLE_CODE_FOR_RECEIVER) #include "IRReceive.hpp" #endif +// Get absolute value of difference of two unsigned values +#if !defined(uintDifferenceAbs) +#define uintDifferenceAbs(a, b) ((a >= b) ? a - b : b - a) +#endif #include "IRSend.hpp" /* diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 1bfa9258d..748df5b49 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -496,7 +496,7 @@ void printTinyReceiverResultMinimal(Print *aSerial) { aSerial->println(); } -#if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR) +#if !defined(STR_HELPER) && !defined(STR) // Helper macro for getting a macro definition as string #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) From 154773ed50ae1632ed0ab1c9d03415fe04a3208a Mon Sep 17 00:00:00 2001 From: Dani Weidman <44669548+danielweidman@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:33:59 -0500 Subject: [PATCH 111/133] Add OpenLASIR protocol support (#1343) Add OpenLASIR support. By: Dani Weidman --- README.md | 10 +- src/IRProtocol.h | 6 +- src/IRProtocol.hpp | 3 +- src/IRReceive.hpp | 11 ++ src/IRSend.hpp | 6 + src/IRremote.hpp | 1 + src/IRremoteInt.h | 7 ++ src/ir_OpenLASIR.hpp | 274 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 src/ir_OpenLASIR.hpp diff --git a/README.md b/README.md index 0e814e8ca..656111fd1 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr ` Hash `,     ` Pronto ` -` BoseWave `,     ` Bang & Olufsen `,     ` Lego `,     ` FAST `,     ` Whynter `,     ` MagiQuest `,     ` Velux ` +` BoseWave `,     ` Bang & Olufsen `,     ` Lego `,     ` FAST `,     ` Whynter `,     ` MagiQuest `,     ` Velux `,     ` OpenLASIR ` Protocols can be switched off and on by defining macros before the line `#include ` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33): @@ -466,7 +466,7 @@ IrReceiver.printIRSendUsage(&Serial); ``` ## Ambiguous protocols -### NEC, Extended NEC, ONKYO +### NEC, Extended NEC, ONKYO, OpenLASIR The **NEC protocol** is defined as 8 bit address and 8 bit command. But the physical address and data fields are each 16 bit wide. The additional 8 bits are used to send the inverted address or command for parity checking.
The **extended NEC protocol** uses the additional 8 parity bit of address for a 16 bit address, thus disabling the parity check for address.
@@ -481,6 +481,8 @@ The decoder interprets this as a NEC 8 bit address 0x00 / 0x32 with correct pari One way to handle this, is to force the library to **always** use the ONKYO protocol interpretation by using `#define DECODE_ONKYO`. Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ONKYO and to revert the parity reducing manually. +The **[OpenLASIR protocol](https://github.com/danielweidman/OpenLASIR)** (like NEC Extended, but with but with 16 bit command [no parity check] and 8 bit address [with parity check]) can also be ambiguous with NEC (and ONKYO). It is recommended to use `#define DECODE_OPENLASIR` when working with OpenLASIR. + ### NEC, NEC2 On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame. This enables an easy distinction between long presses and repeated presses and saves a bit of battery energy. @@ -497,7 +499,7 @@ The `RAW_BUFFER_LENGTH` determines the length of the **byte buffer** where the r **100** is sufficient for standard protocols **up to 48 bits**, with 1 bit consisting of one mark and space. We always require additional 4 bytes, 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit. - **48** bit protocols are PANASONIC, KASEIKYO, SAMSUNG48, RC6. -- **32** bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28) require a **buffer length of 68**. +- **32** bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28), OpenLASIR require a **buffer length of 68**. - **16** bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) require a **buffer length of 36**. - MAGIQUEST requires a buffer length of **112**. - Air conditioners often send a longer protocol data stream **up to 750 bits**. @@ -923,7 +925,7 @@ 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. | +| `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST LEGO_PF, and OpenLASIR from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | | `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | | `USE_THRESHOLD_DECODER` | disabled | If enabled, may give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses and forces value of MARK_EXCESS_MICROS to 0 to save program memory. Requires up to additional 120 bytes program memory. | | `USE_STRICT_DECODER` | disabled | Check for all 4 one and zero protocol timings. Only sensible for development or very exotic requirements. Requires up to 300 additional bytes of program memory. | diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 258204d1b..cbdfa8c5c 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -51,7 +51,8 @@ || 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))) +|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_FAST) || defined(DECODE_WHYNTER) \ +|| defined(DECODE_OPENLASIR))) /* * If no protocol is explicitly enabled, we enable all protocols */ @@ -72,6 +73,7 @@ #define DECODE_MAGIQUEST #define DECODE_WHYNTER #define DECODE_FAST +#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command # endif # if !defined(EXCLUDE_UNIVERSAL_PROTOCOLS) @@ -125,6 +127,7 @@ typedef enum { MAGIQUEST, WHYNTER, /* 30 */ FAST, + OPENLASIR, OTHER } decode_type_t; extern const char *const ProtocolNames[]; // The array of name strings for the decode_type_t enum @@ -193,6 +196,7 @@ struct PulseDistanceWidthProtocolConstants { #define JVC_KHZ 38 #define LG_KHZ 38 #define NEC_KHZ 38 +#define OPENLASIR_KHZ 38 #define SAMSUNG_KHZ 38 #define KASEIKYO_KHZ 37 #define RC5_RC6_KHZ 36 diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index aa058fa28..912089ad6 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -74,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_OpenLASIR[] PROGMEM = "OpenLASIR"; const char string_Other[] PROGMEM = "OTHER"; /* @@ -85,7 +86,7 @@ PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Appl 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_Other + , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST, string_OpenLASIR, string_Other #endif }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index de05bdf3e..56df0acae 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -593,6 +593,7 @@ bool IRrecv::decode() { } #endif + #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) IR_TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode")); if (decodeKaseikyo()) { @@ -694,6 +695,13 @@ bool IRrecv::decode() { } #endif +#if defined(DECODE_OPENLASIR) + IR_TRACE_PRINTLN(F("Attempting OpenLASIR decode")); + if (decodeOpenLASIR()) { + return true; + } +#endif + /* * Try the universal decoder for pulse distance protocols */ @@ -1595,6 +1603,9 @@ void printActiveIRProtocols(Print *aSerial) { #if defined(DECODE_MAGIQUEST) aSerial->print(F("MagiQuest, ")); #endif +#if defined(DECODE_OPENLASIR) + aSerial->print(F("OpenLASIR, ")); +#endif #if defined(DECODE_DISTANCE_WIDTH) aSerial->print(F("Universal Pulse Distance Width, ")); #endif diff --git a/src/IRSend.hpp b/src/IRSend.hpp index a86966174..63ac06ba7 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -265,6 +265,9 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) { } else if (tProtocol == LEGO_PF) { sendLegoPowerFunctions(tAddress, tCommand, tCommand >> 4, tIsRepeat); // send 5 autorepeats + + } else if (tProtocol == OPENLASIR) { + sendOpenLASIR(tAddress, tCommand, aNumberOfRepeats); #endif } else { @@ -382,6 +385,9 @@ size_t IRsend::write(decode_type_t aProtocol, uint16_t aAddress, uint16_t aComma } else if (aProtocol == LEGO_PF) { sendLegoPowerFunctions(aAddress, aCommand, aCommand >> 4, (aNumberOfRepeats < 0)); // send 5 autorepeats, except for dedicated repeats + + } else if (aProtocol == OPENLASIR) { + sendOpenLASIR(aAddress, aCommand, aNumberOfRepeats); #endif } else { diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 07a3e616b..1655279e7 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -281,6 +281,7 @@ void disableLEDFeedback() {}; // dummy function for examples #include "ir_LG.hpp" #include "ir_MagiQuest.hpp" #include "ir_NEC.hpp" +#include "ir_OpenLASIR.hpp" #include "ir_RC5_RC6.hpp" #include "ir_Samsung.hpp" #include "ir_Sony.hpp" diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 47a98f78e..215b6130b 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -359,6 +359,7 @@ class IRrecv { bool decodeLG(); bool decodeMagiQuest(); // not completely standard bool decodeNEC(); + bool decodeOpenLASIR(); bool decodeRC5(); bool decodeRC6(); bool decodeSamsung(); @@ -643,6 +644,11 @@ class IRsend { void sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendApple(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); + void sendOpenLASIRRepeat(); + uint32_t computeOpenLASIRRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand); + void sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); + void sendOpenLASIRRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats = NO_REPEATS); + void sendKaseikyo(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats, uint16_t aVendorCode); // LSB first void sendPanasonic(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first void sendKaseikyo_Denon(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first @@ -745,6 +751,7 @@ class IRsend { extern IRsend IrSender; void sendNECSpecialRepeat(); +void sendOpenLASIRSpecialRepeat(); void sendLG2SpecialRepeat(); void sendSamsungLGSpecialRepeat(); diff --git a/src/ir_OpenLASIR.hpp b/src/ir_OpenLASIR.hpp new file mode 100644 index 000000000..d91e66815 --- /dev/null +++ b/src/ir_OpenLASIR.hpp @@ -0,0 +1,274 @@ +/* + * ir_OpenLASIR.hpp + * + * Contains functions for receiving and sending the OpenLASIR IR Protocol. + * OpenLASIR is a modified NEC protocol with 8-bit validated address (with inverted complement) + * and 16-bit command (no error check on command). This is the opposite of NEC Extended, + * which has 16-bit address and 8-bit validated command. + * + * Protocol details: + * - Bits 0-7: Address (8 bits, Block ID) + * - Bits 8-15: ~Address (8-bit inverted copy, for error checking) + * - Bits 16-31: Command (16 bits, no error check) + * - Same timing as NEC: 38 kHz carrier, 9ms leading mark, 4.5ms leading space, + * 562.5us bit mark, 1687.5us "1" space, 562.5us "0" space, 562.5us stop bit + * - LSB first, pulse distance encoding + * - Special NEC-style repeat frame (9ms mark + 2.25ms space + stop bit) + * + * See: https://github.com/danielweidman/OpenLASIR + * + * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * + ************************************************************************************ + * MIT License + * + * Copyright (c) 2025 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ************************************************************************************ + */ +#ifndef _IR_OPENLASIR_HPP +#define _IR_OPENLASIR_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 + * @{ + */ +//============================================================================== +// OpenLASIR - Modified NEC Extended Protocol +// 8-bit validated address + 16-bit command +//============================================================================== +/* + * OpenLASIR uses the same timing as NEC but rearranges the address/command structure: + * - 8-bit address with 8-bit inverted complement (for error checking) + * - 16-bit command with no error check + * + * This is the opposite of NEC Extended, which uses 16-bit address and 8-bit validated command. + * + * The timing constants are shared with NEC (defined in ir_NEC.hpp): + * NEC_UNIT, NEC_HEADER_MARK, NEC_HEADER_SPACE, NEC_BIT_MARK, + * NEC_ONE_SPACE, NEC_ZERO_SPACE, NEC_REPEAT_HEADER_SPACE, etc. + * + * IRP notation: + * {38.0k,564}<1,-1|1,-3>(16,-8,A:8,~A:8,C:16,1,^108m,(16,-4,1,^108m)*) + * A = 8-bit address (Block ID) + * ~A = inverted address (error check) + * C = 16-bit command (Device ID + Mode + Data) + */ + +// OpenLASIR address and command bit widths +#define OPENLASIR_ADDRESS_BITS 16 // 8 bit address + 8 bit inverted address +#define OPENLASIR_COMMAND_BITS 16 // 16 bit command, no error check +#define OPENLASIR_BITS (OPENLASIR_ADDRESS_BITS + OPENLASIR_COMMAND_BITS) // 32 bits total + +// Timing is identical to NEC (reuse NEC_* constants from ir_NEC.hpp) + +struct PulseDistanceWidthProtocolConstants const OpenLASIRProtocolConstants PROGMEM = { + OPENLASIR, + NEC_KHZ, + NEC_HEADER_MARK, + NEC_HEADER_SPACE, + NEC_BIT_MARK, + NEC_ONE_SPACE, + NEC_BIT_MARK, + NEC_ZERO_SPACE, + PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, + (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), + &sendOpenLASIRSpecialRepeat +}; + +/************************************ + * Start of send and decode functions + ************************************/ + +/** + * Send special OpenLASIR repeat frame (same as NEC repeat frame). + * Repeat commands should be sent in a 110 ms raster. + */ +void IRsend::sendOpenLASIRRepeat() { + enableIROut(NEC_KHZ); // 38 kHz + mark(NEC_HEADER_MARK); // + 9000 + space(NEC_REPEAT_HEADER_SPACE); // - 2250 + mark(NEC_BIT_MARK); // + 560 +} + +/** + * Static function variant of IRsend::sendOpenLASIRRepeat + * For use in ProtocolConstants. Saves up to 250 bytes compared to a member function. + */ +void sendOpenLASIRSpecialRepeat() { + IrSender.enableIROut(NEC_KHZ); // 38 kHz + IrSender.mark(NEC_HEADER_MARK); // + 9000 + IrSender.space(NEC_REPEAT_HEADER_SPACE); // - 2250 + IrSender.mark(NEC_BIT_MARK); // + 560 +} + +/** + * Compute the raw 32-bit data for an OpenLASIR frame from 8-bit address and 16-bit command. + * Address is sent as: [address:8][~address:8] (inverted complement for error checking) + * Command is sent as: [command:16] (no error check) + * + * @param aAddress 8-bit address (Block ID). Only lower 8 bits are used. + * @param aCommand 16-bit command (contains Device ID, Mode, and Data). + * @return 32-bit raw data ready for transmission. + */ +uint32_t IRsend::computeOpenLASIRRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand) { + LongUnion tRawData; + + // Address: 8 bit address + 8 bit inverted address for error checking + tRawData.UByte.LowByte = aAddress; + tRawData.UByte.MidLowByte = ~aAddress; + + // Command: full 16 bits, no error check + tRawData.UWord.HighWord = aCommand; + + return tRawData.ULong; +} + +/** + * Send an OpenLASIR frame with special NEC-style repeats. + * There is NO delay after the last sent repeat! + * + * @param aAddress 8-bit address (Block ID). Only lower 8 bits are used. + * @param aCommand 16-bit command (Device ID + Mode + Data). + * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + */ +void IRsend::sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { + sendPulseDistanceWidth_P(&OpenLASIRProtocolConstants, + computeOpenLASIRRawDataAndChecksum(aAddress, aCommand), OPENLASIR_BITS, aNumberOfRepeats); +} + +/** + * Send raw 32-bit OpenLASIR data. + * @param aRawData The pre-computed 32-bit raw data. + * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + */ +void IRsend::sendOpenLASIRRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats) { + sendPulseDistanceWidth_P(&OpenLASIRProtocolConstants, aRawData, OPENLASIR_BITS, aNumberOfRepeats); +} + +/** + * Decode an OpenLASIR frame. + * + * OpenLASIR uses the same physical layer as NEC but with different address/command structure: + * - 8-bit address with inverted complement (error check on address) + * - 16-bit command without error check + * + * The decoder validates the address by checking that the second byte is the bitwise + * inverse of the first byte. The full 16-bit command is returned as-is. + * + * @return true if a valid OpenLASIR frame was decoded. + */ +bool IRrecv::decodeOpenLASIR() { + /* + * First check for right data length + * Next check start bit + * Next try the decode + */ + + // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. + if (decodedIRData.rawlen != ((2 * OPENLASIR_BITS) + 4) && (decodedIRData.rawlen != 4)) { + IR_DEBUG_PRINT(F("OpenLASIR: ")); + IR_DEBUG_PRINT(F("Data length=")); + IR_DEBUG_PRINT(decodedIRData.rawlen); + IR_DEBUG_PRINTLN(F(" is not 68 or 4")); + return false; + } + + // Check header "mark" - this must be done for repeat and data + if (!matchMark(irparams.rawbuf[1], NEC_HEADER_MARK)) { + return false; + } + + // Check for repeat - here we have another header space length + if (decodedIRData.rawlen == 4) { + // Only claim this repeat if the last decoded protocol was OpenLASIR + if (lastDecodedProtocol == OPENLASIR + && matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) + && matchMark(irparams.rawbuf[3], NEC_BIT_MARK)) { + decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; + decodedIRData.address = lastDecodedAddress; + decodedIRData.command = lastDecodedCommand; + decodedIRData.protocol = OPENLASIR; + return true; + } + return false; + } + + // Check command header space + if (!matchSpace(irparams.rawbuf[2], NEC_HEADER_SPACE)) { +#if defined(LOCAL_DEBUG) + Serial.print(F("OpenLASIR: ")); + Serial.println(F("Header space length is wrong")); +#endif + return false; + } + + // Decode the pulse distance data using NEC timing + decodePulseDistanceWidthData_P(&OpenLASIRProtocolConstants, OPENLASIR_BITS); + + // Success - now interpret the 32 raw bits + LongUnion tValue; + tValue.ULong = decodedIRData.decodedRawData; + + // Validate address: second byte must be inverted first byte + if (tValue.UByte.LowByte != (uint8_t)(~tValue.UByte.MidLowByte)) { + // Address validation failed - this is not a valid OpenLASIR frame + IR_DEBUG_PRINT(F("OpenLASIR: ")); + IR_DEBUG_PRINTLN(F("Address validation failed")); + return false; + } + + /* + * Disambiguation with standard NEC: + * If the command also has a valid inverted pattern (upper 8 bits == ~lower 8 bits), + * then this looks like a standard NEC frame, not OpenLASIR. + * By design, OpenLASIR uses 16-bit commands that should NOT have this property, + * so we let the NEC decoder handle these frames instead. + * (See OpenLASIR spec: "This is to prevent OpenLASIR packets from causing issues + * with NEC devices except in very rare cases of collisions.") + */ + if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { + IR_DEBUG_PRINT(F("OpenLASIR: ")); + IR_DEBUG_PRINTLN(F("Command has valid inverse - looks like standard NEC, skipping")); + return false; + } + + // Valid OpenLASIR frame + decodedIRData.protocol = OPENLASIR; + decodedIRData.address = tValue.UByte.LowByte; // 8-bit validated address (Block ID) + decodedIRData.command = tValue.UWord.HighWord; // 16-bit command (Device ID + Mode + Data) + decodedIRData.numberOfBits = OPENLASIR_BITS; + + // Check for repeat (same frame sent again within repeat window) + checkForRepeatSpaceTicksAndSetFlag(NEC_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK); + + return true; +} + +/** @}*/ +#if defined(LOCAL_DEBUG) +#undef LOCAL_DEBUG +#endif +#endif // _IR_OPENLASIR_HPP From 142695b277c39fad74777f29b74209999448d279 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 11 Feb 2026 01:50:35 +0100 Subject: [PATCH 112/133] Examples --- .github/workflows/LibraryBuild.yml | 4 ++-- Contributors.md | 1 + README.md | 2 +- changelog.md | 1 + examples/AllProtocolsOnLCD/ADCUtils.h | 4 ++-- examples/AllProtocolsOnLCD/ADCUtils.hpp | 14 +++++++------- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 8 -------- examples/ControlRelay/PinDefinitionsAndMore.h | 8 -------- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- examples/IRremoteInfo/IRremoteInfo.ino | 4 +++- examples/MicroGirs/PinDefinitionsAndMore.h | 8 -------- .../MultipleReceivers/PinDefinitionsAndMore.h | 8 -------- .../ReceiveAndSend/PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- examples/ReceiveDemo/PinDefinitionsAndMore.h | 8 -------- examples/ReceiveDump/PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- .../SendAndReceive/PinDefinitionsAndMore.h | 8 -------- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 8 -------- examples/SendDemo/PinDefinitionsAndMore.h | 8 -------- examples/SendDemo/SendDemo.ino | 5 ++++- .../PinDefinitionsAndMore.h | 8 -------- .../SendProntoDemo/PinDefinitionsAndMore.h | 8 -------- examples/SendRawDemo/PinDefinitionsAndMore.h | 8 -------- .../SimpleReceiver/PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- .../PinDefinitionsAndMore.h | 8 -------- examples/SimpleSender/PinDefinitionsAndMore.h | 8 -------- examples/TinyReceiver/PinDefinitionsAndMore.h | 8 -------- examples/TinySender/PinDefinitionsAndMore.h | 8 -------- examples/UnitTest/PinDefinitionsAndMore.h | 8 -------- examples/UnitTest/UnitTest.ino | 5 ++++- src/IRSend.hpp | 18 +++++++++++++++++- 35 files changed, 42 insertions(+), 216 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 4a9e5ef01..d7eac36b6 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -191,12 +191,12 @@ jobs: # # - arduino-boards-fqbn: megaTinyCore:megaavr:atxy4:chip=1604,clock=16internal # arduino-platform: megaTinyCore:megaavr -# platform-url: http://drazzy.com/package_drazzy.com_index.json +# platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_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 +# platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json # sketches-exclude: AllProtocolsOnLCD # diff --git a/Contributors.md b/Contributors.md index 90a817a19..94ad676a8 100644 --- a/Contributors.md +++ b/Contributors.md @@ -36,5 +36,6 @@ These are the active contributors of this project that you may contact if there - [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. - [silen72](https://github.com/silen72) Fixing ESP32 multiple attach bug #1324. +- [danielweidman](https://github.com/danielweidman) Adding OpenLASIR protocol. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/README.md b/README.md index 656111fd1..698596468 100644 --- a/README.md +++ b/README.md @@ -1007,7 +1007,7 @@ Digispark boards are tested only with [ATTinyCore](https://github.com/SpenceKond - ATtiny84, 85, 167 (Digispark + Digispark Pro) - SAMD (Zero, MKR*, **but not DUE, the latter is SAM architecture**) - ESP8266 -- ESP32 (ESP32-C3 since board package 2.0.2 from Espressif). New CPUs (as of January 2025) are not guaranteed to work! +- ESP32, ESP32-C3 since board package 2.0.2 from Espressif. Other CPUs are not tested! SP32-S3 is not supported (yet). - Sparkfun Pro Micro - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 diff --git a/changelog.md b/changelog.md index 058221fc5..e03109626 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Fixed missing initialization with pinMode() for feedback LED. - Fixed bitmask error in sendBiphaseData() when not sending start bit. - Improved decodeSamsung(). +- OpenLASIR protocol added by [danielweidman](https://github.com/danielweidman). # 4.5.0 - Added support for multiple receiver instances. diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 20d759b4c..eb4928e72 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -30,8 +30,8 @@ #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 -#define MAX_ADC_VALUE 1023L +#define READING_FOR_AREF 1024 // Datasheet 24.2: The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB +#define MAX_ADC_VALUE 1023 // PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz #define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 36ac867d3..12357992c 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -43,7 +43,7 @@ * with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV. */ #if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT) -#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100UL // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values +#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100 // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values #endif // Union to speed up the combination of low and high bytes to a word @@ -542,7 +542,7 @@ 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 ((READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC); + return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC); } /* @@ -554,7 +554,7 @@ uint16_t getVCCVoltageReadingFor1_1VoltReference(void) { /* * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement */ - return ((READING_FOR_AREF * READING_FOR_AREF) / tVCC); + return (((uint32_t)READING_FOR_AREF * READING_FOR_AREF) / tVCC); } /* @@ -578,7 +578,7 @@ uint16_t getVCCVoltageMillivolt(void) { /* * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement */ - return ((READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC); + return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC); } /* @@ -617,7 +617,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 = (READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw; + sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw; } /* @@ -638,7 +638,7 @@ void readVCCVoltageMillivolt(void) { /* * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement */ - sVCCVoltageMillivolt = (READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw; + sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw; } /* @@ -700,7 +700,7 @@ bool isVCCUSBPowered(Print *aSerial) { */ bool isVCCUndervoltageMultipleTimes() { /* - * Check VCC every VCC_CHECK_PERIOD_MILLIS (10) seconds + * Check VCC every VCC_CHECK_PERIOD_MILLIS - default is 10 seconds */ if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) { sLastVCCCheckMillis = millis(); diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino index 25d0f09d9..4aa3c603d 100644 --- a/examples/IRremoteInfo/IRremoteInfo.ino +++ b/examples/IRremoteInfo/IRremoteInfo.ino @@ -11,6 +11,8 @@ */ #include +//#define DEBUG + //#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 240 bytes program memory if IrSender.write is used //#define SEND_PWM_BY_TIMER //#define USE_NO_SEND_PWM @@ -213,7 +215,7 @@ void dumpSignalParams() { void dumpDebugMode() { Serial.print(F("Debug Mode: ")); -#if DEBUG +#if defined(DEBUG) Serial.println(F("ON")); #else Serial.println(F("OFF (Normal)")); diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 1d16d4cbf..9d669f421 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -65,7 +65,10 @@ IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRaw //0x10, 0xA0, 0x0, 0x0, /*0xA010*/}; #endif -const uint16_t rawIRTimingsNEC[] PROGMEM +const uint16_t rawIRTimingsNEC[] +#if defined(__AVR__) +PROGMEM // this crashes on ESP8266 +#endif = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index efb3b6f3f..df24c30e1 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -356,11 +356,3 @@ void noTone(uint8_t aPinNumber){ #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif - -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 2cf864e79..ca5007ee8 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -142,7 +142,10 @@ uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/ #endif // if this definition is contained in a function, the address, the compiler uses is wrong :-( -const uint16_t rawIRTimingsNEC[] PROGMEM +const uint16_t rawIRTimingsNEC[] +#if defined(__AVR__) +PROGMEM // this crashes on ESP8266 +#endif = { 9000, 4500/*Start bit*/, 560, 560, 560, 560, 560, 1690, 560, 560/*0010 0x4 of 16 bit address LSB first*/, 560, 560, 560, 560, 560, 560, 560, 560/*0000*/, 560, 1690, 560, 1690, 560, 560, 560, 1690/*1101 0xB*/, 560, 1690, 560, 1690, 560, 1690, 560, 1690/*1111*/, 560, 560, 560, 560, 560, 560, 560, 1690/*0001 0x08 of command LSB first*/, 560, 560, 560, 560, 560, 560, 560, diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 63ac06ba7..56a7ebf9d 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -408,6 +408,14 @@ void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLe // Set IR carrier frequency enableIROut(aIRFrequencyKilohertz); +#if defined(LOCAL_DEBUG) + Serial.print(F("aPGMBufferWithMicroseconds=0x")); + Serial.print((uint32_t) aBufferWithMicroseconds, HEX); + Serial.print(F(" [0]=")); + Serial.println(aBufferWithMicroseconds[0]); // this crashes on ESP8266 if aBufferWithMicroseconds is PROGMEM + Serial.flush(); +#endif + /* * Raw data starts with a mark. */ @@ -504,7 +512,7 @@ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_ # 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); + Serial.println((uint16_t) aPGMBufferWithMicroseconds, HEX); #endif for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) { @@ -532,6 +540,14 @@ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz, uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { +#if defined(LOCAL_DEBUG) + Serial.print(F("aPGMBufferWithMicroseconds=0x")); + Serial.print((uint32_t) aPGMBufferWithMicroseconds, HEX); + Serial.print(F(" [0]=")); + Serial.println(aPGMBufferWithMicroseconds[0]); // this crashes on ESP8266 + Serial.flush(); +#endif + uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); From 9be2862580d67b24b4782eedfeae2053e294eb22 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 11 Feb 2026 10:25:48 +0100 Subject: [PATCH 113/133] OpenLASIR continued --- .github/workflows/LibraryBuild.yml | 1 + README.md | 20 +++- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 12 +- examples/ControlRelay/PinDefinitionsAndMore.h | 12 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- examples/MicroGirs/PinDefinitionsAndMore.h | 12 +- .../MultipleReceivers/MultipleReceivers.ino | 5 + .../MultipleReceivers/PinDefinitionsAndMore.h | 12 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 12 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- .../SendAndReceive/PinDefinitionsAndMore.h | 12 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 12 +- examples/SendDemo/PinDefinitionsAndMore.h | 12 +- examples/SendDemo/SendDemo.ino | 7 +- .../PinDefinitionsAndMore.h | 12 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 12 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 12 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- .../PinDefinitionsAndMore.h | 12 +- examples/SimpleSender/PinDefinitionsAndMore.h | 12 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 12 +- examples/TinySender/PinDefinitionsAndMore.h | 12 +- examples/UnitTest/PinDefinitionsAndMore.h | 12 +- examples/UnitTest/UnitTest.ino | 12 +- examples/UnitTest/UnitTest.log | 36 ++++++ src/IRProtocol.h | 40 +------ src/IRProtocol.hpp | 5 +- src/IRReceive.hpp | 5 +- src/IRSend.hpp | 2 +- src/IRremoteInt.h | 7 +- src/ir_OpenLASIR.hpp | 107 +++++++++++++----- 37 files changed, 447 insertions(+), 100 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index d7eac36b6..efeea7cab 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -96,6 +96,7 @@ jobs: ReceiveDemo: -DUSE_THRESHOLD_DECODER -DEBUG -DTRACE IRremoteExtensionTest: -DIR_SEND_PIN=3 -DEBUG -DTRACE TinyReceiver: -DUSE_CALLBACK_FOR_TINY_RECEIVER -DEBUG -DTRACE + UnitTest: -DEBUG # otherwise Sketch uses 32486 bytes (100%) of program storage space. Maximum is 32256 bytes. All: -DEBUG -DTRACE - arduino-boards-fqbn: arduino:avr:uno|USE_NO_SEND_PWM diff --git a/README.md b/README.md index 698596468..160e96bc5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) - [Common issues when using IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-issues-when-using-irremote) - [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#migrating-legacy-projects-to-the-latest-version) - * [New features of version 4.5](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-of-version-45) + * [New features and changes in version 4.5](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-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) @@ -64,6 +64,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr + [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) +- [Feedback LED](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#feedback-led) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) * [Receiving stops after analogWrite() or tone() or after running a motor](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor) * [Receiving sets overflow flag](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-sets-overflow-flag) @@ -481,7 +482,7 @@ The decoder interprets this as a NEC 8 bit address 0x00 / 0x32 with correct pari One way to handle this, is to force the library to **always** use the ONKYO protocol interpretation by using `#define DECODE_ONKYO`. Another way is to check if `IrReceiver.decodedIRData.protocol` is NEC and not ONKYO and to revert the parity reducing manually. -The **[OpenLASIR protocol](https://github.com/danielweidman/OpenLASIR)** (like NEC Extended, but with but with 16 bit command [no parity check] and 8 bit address [with parity check]) can also be ambiguous with NEC (and ONKYO). It is recommended to use `#define DECODE_OPENLASIR` when working with OpenLASIR. +The **[OpenLASIR protocol](https://github.com/danielweidman/OpenLASIR)** is binary identical to ONKYO but has a different semantics. It is recommended to disable `#define DECODE_ONKYO` and enable `#define DECODE_OPENLASIR` when working with OpenLASIR. ### NEC, NEC2 On a long press, the **NEC protocol** does not repeat its frame, it sends a special short repeat frame. @@ -725,6 +726,21 @@ void loop() {} The FAST protocol can be received by IRremote and TinyIRReceiver. +# Feedback LED +The feedback LED output is enabled by default. This means that **the LED is on when we receive or send a mark**. +The feedback LED code can be completely removed at compile time using the following macros: +- `NO_LED_RECEIVE_FEEDBACK_CODE` for receiving +- `NO_LED_SEND_FEEDBACK_CODE` for sending +- `NO_LED_FEEDBACK_CODE` for receiving and sending + +### Receiving +For receiving, feedback LED can be activated or deactivated programmatically by `enableLEDFeedback()`, `disableLEDFeedback()` or `setLEDFeedback(bool aEnableLEDFeedback)`.
+The starting value is set by the second parameter of `begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)`. You can use the macros `ENABLE_LED_FEEDBACK` and `DISABLE_LED_FEEDBACK` for the second parameter. + +### Sending +LED feedback is **always enabled** when sending and cannot be deactivated programmatically. +It can only be deactivated at compile time. + # FAQ and hints ## Receiving stops after analogWrite() or tone() or after running a motor. The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index 24c7495ef..3792296ae 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -143,6 +143,11 @@ void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance) { } +/* + * This handler is called in ISR context after IrReceiver.ReceiveInterruptHandler() if SUPPORT_MULTIPLE_RECEIVER_INSTANCES is active. + * Here we just call the standard ReceiveInterruptHandler for the second receiver. + * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving. + */ void UserIRReceiveTimerInterruptHandler() { MySecondIrReceiver.ReceiveInterruptHandler(); } diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 9d669f421..b916d9679 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -435,6 +435,11 @@ void loop() { IrSender.sendMagiQuest(0x6BCD0000 | (uint32_t) sAddress, s16BitCommand); // we have 31 bit address delay(DELAY_AFTER_SEND); + Serial.println(F("Send OpenLASIR")); + Serial.flush(); + IrSender.sendOpenLASIR(sAddress & 0xFF, sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE, sRepeats); + delay(DELAY_AFTER_SEND); + // Bang&Olufsen must be sent with 455 kHz // Serial.println(F("Send Bang&Olufsen")); // Serial.flush(); diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index df24c30e1..fc89e0a96 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -4,7 +4,7 @@ * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * - * Copyright (C) 2021-2023 Armin Joachimsmeyer + * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -44,6 +44,7 @@ * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 + * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 @@ -181,6 +182,7 @@ #define TONE_PIN 42 // Dummy for examples using it# #elif defined(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) +// ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 @@ -188,12 +190,20 @@ #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) +// ESP32 - C3 other #define NO_LED_FEEDBACK_CODE // The WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working... #define IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 +#elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) +// ESP32 - S3 - !!! NOT tested !!! +#define IR_RECEIVE_PIN 15 // alternatively 13 +#define IR_SEND_PIN 16 // alternatively 14 +#define TONE_PIN 17 +#define APPLICATION_PIN 18 + #elif defined(ESP32) #include diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index ca5007ee8..5a50d6821 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -102,6 +102,7 @@ #define DECODE_BOSEWAVE #define DECODE_MAGIQUEST +#define DECODE_OPENLASIR #define DECODE_FAST //#define DECODE_WHYNTER @@ -903,6 +904,15 @@ void loop() { delay(DELAY_AFTER_SEND); #endif +#if defined(DECODE_OPENLASIR) + Serial.println(F("Send OpenLASIR mode fire and color orange")); + Serial.flush(); + IrSender.sendOpenLASIR(sAddress & 0xFF, sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE, sRepeats); + checkReceive(sAddress & 0xFF, IrSender.computeOpenLASIRRawCommand(sCommand, OPENLASIR_MODE_LASER_TAG_FIRE,OPENLASIR_COLOR_ORANGE)); + delay(DELAY_AFTER_SEND); +#endif + + #if defined(DECODE_LEGO_PF) Serial.println(F("Send Lego with 2 channel and with 4 command bits")); Serial.flush(); diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 24cdb3168..50ae4c4f5 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -675,6 +675,24 @@ rawData[112]: Duration=64000us +Send OpenLASIR mode fire and color orange +Protocol=Onkyo Address=0xF1, Command=0x6076, Raw-Data=0x60760EF1, 32 bits, LSB first, Gap=791350us, Duration=66750us +Send with: IrSender.sendOnkyo(0xF1, 0x6076, ); +rawIRTimings[68]: + -791350 + +8900,-4450 + + 600,-1650 + 650,- 450 + 600,- 550 + 650,- 500 + + 650,-1550 + 650,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,-1650 + + 650,- 450 + 600,- 550 + 600,- 550 + 600,- 500 + + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 600,- 550 + 650,- 500 + 650,- 450 + + 600,- 550 + 600,-1650 + 650,-1600 + 600,- 500 + + 600 +Duration=66750us + + Send Lego with 2 channel and with 4 command bits Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169, 16 bits, MSB first, Gap=791500us, Duration=9950us Send with: IrSender.sendLego(0x1, 0x16, ); @@ -1216,6 +1234,24 @@ rawData[112]: Duration=63700us +Send OpenLASIR mode fire and color orange +Protocol=Onkyo Address=0xF2, Command=0x6087, Raw-Data=0x60870DF2, 32 bits, LSB first, Gap=791650us, Duration=65650us +Send with: IrSender.sendOnkyo(0xF2, 0x6087, ); +rawIRTimings[68]: + -791650 + +8950,-4400 + + 650,- 450 + 650,-1600 + 650,- 500 + 650,- 450 + + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1600 + + 600,-1600 + 600,- 550 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,- 550 + 600,- 500 + 650,- 500 + + 650,-1600 + 650,-1600 + 650,-1550 + 650,- 500 + + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,- 500 + 600,- 500 + + 600,- 550 + 650,-1600 + 600,-1600 + 650,- 500 + + 600 +Duration=65650us + + Send Lego with 2 channel and with 4 command bits Protocol=Lego Address=0x2, Command=0x17, Raw-Data=0x217B, 16 bits, MSB first, Gap=791750us, Duration=10550us Send with: IrSender.sendLego(0x2, 0x17, ); diff --git a/src/IRProtocol.h b/src/IRProtocol.h index cbdfa8c5c..1c0888414 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,6 @@ * 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 @@ -95,40 +94,13 @@ * !!!Must be the same order as ProtocolNames in IRReceive.hpp!!! */ typedef enum { - UNKNOWN = 0, - PULSE_WIDTH, - PULSE_DISTANCE, - APPLE, - DENON, - JVC, - LG, - LG2, - NEC, - NEC2, /* 10 NEC with full frame as repeat */ - ONKYO, - PANASONIC, - KASEIKYO, - KASEIKYO_DENON, - KASEIKYO_SHARP, - KASEIKYO_JVC, - KASEIKYO_MITSUBISHI, - RC5, - RC6, - RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ + UNKNOWN = 0, PULSE_WIDTH, PULSE_DISTANCE, APPLE, DENON, JVC, LG, LG2, NEC, NEC2, /* 10 NEC with full frame as repeat */ + ONKYO, PANASONIC, KASEIKYO, KASEIKYO_DENON, KASEIKYO_SHARP, KASEIKYO_JVC, KASEIKYO_MITSUBISHI, RC5, RC6, RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ SAMSUNG, /* 20*/ - SAMSUNGLG, - SAMSUNG48, - SHARP, - SONY, + SAMSUNGLG, SAMSUNG48, SHARP, SONY, /* Now the exotic protocols */ - BANG_OLUFSEN, - BOSEWAVE, - LEGO_PF, - MAGIQUEST, - WHYNTER, /* 30 */ - FAST, - OPENLASIR, - OTHER + BANG_OLUFSEN, BOSEWAVE, LEGO_PF, MAGIQUEST, WHYNTER, /* 30 */ + FAST, OPENLASIR, OTHER } decode_type_t; extern const char *const ProtocolNames[]; // The array of name strings for the decode_type_t enum diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 912089ad6..77c04a529 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2009-2023 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer + * Copyright (c) 2009-2026 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 @@ -86,7 +86,8 @@ PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Appl 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_OpenLASIR, string_Other + , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST, string_OpenLASIR, + string_Other #endif }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 56df0acae..9ba833405 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2009-2025 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer + * Copyright (c) 2009-2026 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 @@ -276,7 +276,7 @@ void IRrecv::ReceiveInterruptHandler() { /* * 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 + * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving */ void IRReceiveTimerInterruptHandler() { IrReceiver.ReceiveInterruptHandler(); @@ -593,7 +593,6 @@ bool IRrecv::decode() { } #endif - #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) IR_TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode")); if (decodeKaseikyo()) { diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 56a7ebf9d..0cab2c010 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2009-2025 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer + * Copyright (c) 2009-2026 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 diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 215b6130b..9cab19717 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2015-2025 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer + * Copyright (c) 2015-2026 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 @@ -646,8 +646,13 @@ class IRsend { void sendOpenLASIRRepeat(); uint32_t computeOpenLASIRRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand); + uint16_t computeOpenLASIRRawCommand(uint8_t aDeviceID, uint8_t aMode, uint8_t aData); void sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); + void sendOpenLASIR(uint8_t aAddress, uint8_t aDeviceID, uint8_t aMode, uint8_t aData, int_fast8_t aNumberOfRepeats); void sendOpenLASIRRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats = NO_REPEATS); +#define OpenLASIR_GetMDeviceId(aCommand) (aCommand & 0xFF) +#define OpenLASIR_GetMode(aCommand) ((aCommand >> 8) & 0x1F) +#define OpenLASIR_GetData(aCommand) (aCommand >> 13) void sendKaseikyo(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats, uint16_t aVendorCode); // LSB first void sendPanasonic(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first diff --git a/src/ir_OpenLASIR.hpp b/src/ir_OpenLASIR.hpp index d91e66815..125e3d04c 100644 --- a/src/ir_OpenLASIR.hpp +++ b/src/ir_OpenLASIR.hpp @@ -22,7 +22,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2025 + * Copyright (c) 2025-2026 Daniel Weidmann, Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,6 +63,11 @@ * OpenLASIR uses the same timing as NEC but rearranges the address/command structure: * - 8-bit address with 8-bit inverted complement (for error checking) * - 16-bit command with no error check + * Bits 0-7: Block ID (8 bits) ↠Address low byte + * Bits 8-15: ~Block ID (8 bits) ↠Address high byte (inverted, for error check) + * Bits 16-23: Device ID (8 bits) ↠Command bits 0-7 + * Bits 24-28: Mode (5 bits) ↠Command bits 8-12 + * Bits 29-31: Data (color, etc.) (3 bits) ↠Command bits 13-15 * * This is the opposite of NEC Extended, which uses 16-bit address and 8-bit validated command. * @@ -82,21 +87,36 @@ #define OPENLASIR_COMMAND_BITS 16 // 16 bit command, no error check #define OPENLASIR_BITS (OPENLASIR_ADDRESS_BITS + OPENLASIR_COMMAND_BITS) // 32 bits total -// Timing is identical to NEC (reuse NEC_* constants from ir_NEC.hpp) +/* + * Constants for Mode + */ +#define OPENLASIR_MODE_LASER_TAG_FIRE 0 // Laser tag shot. Data = color. +#define OPENLASIR_MODE_USER_PRESENCE_ANNOUNCEMENT 1 // User device saying "I'm here." No response expected. +#define OPENLASIR_MODE_BASE_STATION_PRESENCE_ANNOUNCEMENT 2 // Fixed base station saying "I'm here." +#define OPENLASIR_MODE_USER_TO_USER_HANDSHAKE_INITIATION 3 // User badge initiates handshake with another user badge. +#define OPENLASIR_MODE_USER_TO_USER_HANDSHAKE_RESPONSE 4 // Response to a user-to-user handshake initiation. +#define OPENLASIR_MODE_USER_TO_BASE_STATION_HANDSHAKE_INITIATION 5 // User badge initiates handshake with a base station. +#define OPENLASIR_MODE_USER_TO_BASE_STATION_HANDSHAKE_RESPONSE 6 // Base station responds to a user-initiated handshake. +#define OPENLASIR_MODE_BASE_STATION_TO_USER_HANDSHAKE_INITIATION 7 // Base station initiates handshake with a user badge. +#define OPENLASIR_MODE_BASE_STATION_TO_USER_HANDSHAKE_RESPONSE 8 // User badge responds to a base-station-initiated handshake. +#define OPENLASIR_MODE_COLOR_SET_TEMPORARY 9 // Tell a badge to display a color temporarily. +#define OPENLASIR_MODE_COLOR_SET_PERMANENT 10 // Tell a badge to display a color and "remember" it according to some device-specific logic. +#define OPENLASIR_MODE_GENERAL_INTERACT 11 // Tell a device to execute a general "interact" action. The specific behavior is defined by the receiver. +// modes 12 to 31 are reserved for future use + +/* + * Constants for Data / Color + */ +#define OPENLASIR_COLOR_CYAN 0 // (0, 255, 255) +#define OPENLASIR_COLOR_MAGENTA 1 // (255, 0, 255) +#define OPENLASIR_COLOR_YELLOW 2 // (255, 255, 0) +#define OPENLASIR_COLOR_GREEN 3 // (0, 255, 0) +#define OPENLASIR_COLOR_RED 4 // (255, 0, 0) +#define OPENLASIR_COLOR_BLUE 5 // (0, 0, 255) +#define OPENLASIR_COLOR_ORANGE 6 // (255, 165, 0) +#define OPENLASIR_COLOR_WHITE 7 // (255, 255, 255) -struct PulseDistanceWidthProtocolConstants const OpenLASIRProtocolConstants PROGMEM = { - OPENLASIR, - NEC_KHZ, - NEC_HEADER_MARK, - NEC_HEADER_SPACE, - NEC_BIT_MARK, - NEC_ONE_SPACE, - NEC_BIT_MARK, - NEC_ZERO_SPACE, - PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, - (NEC_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), - &sendOpenLASIRSpecialRepeat -}; +// Timing is identical to NEC (reuse NEC_* constants from ir_NEC.hpp) /************************************ * Start of send and decode functions @@ -107,10 +127,7 @@ struct PulseDistanceWidthProtocolConstants const OpenLASIRProtocolConstants PROG * Repeat commands should be sent in a 110 ms raster. */ void IRsend::sendOpenLASIRRepeat() { - enableIROut(NEC_KHZ); // 38 kHz - mark(NEC_HEADER_MARK); // + 9000 - space(NEC_REPEAT_HEADER_SPACE); // - 2250 - mark(NEC_BIT_MARK); // + 560 + sendNECRepeat(); } /** @@ -118,10 +135,7 @@ void IRsend::sendOpenLASIRRepeat() { * For use in ProtocolConstants. Saves up to 250 bytes compared to a member function. */ void sendOpenLASIRSpecialRepeat() { - IrSender.enableIROut(NEC_KHZ); // 38 kHz - IrSender.mark(NEC_HEADER_MARK); // + 9000 - IrSender.space(NEC_REPEAT_HEADER_SPACE); // - 2250 - IrSender.mark(NEC_BIT_MARK); // + 560 + sendNECSpecialRepeat(); } /** @@ -146,6 +160,24 @@ uint32_t IRsend::computeOpenLASIRRawDataAndChecksum(uint8_t aAddress, uint16_t a return tRawData.ULong; } +/** + * Compute the raw 32-bit data for an OpenLASIR frame from 8-bit address, 8-bit DeviceID, 5-bit Mode and 3-bit Data. + * + * @param aAddress 8-bit address (Block ID). Only lower 8 bits are used. + * @param aDeviceID 8-bit Device ID. + * @param aMode 5-bit Mode. + * @param aData 3-bit Data (color, etc.). + * @return 32-bit raw data ready for transmission. + */ +uint16_t IRsend::computeOpenLASIRRawCommand(uint8_t aDeviceID, uint8_t aMode, uint8_t aData) { + WordUnion tRawCommand; + + tRawCommand.UByte.LowByte = aDeviceID; + tRawCommand.UByte.HighByte = (aMode & 0x1F) | ((aData & 0x07) << 5); + + return tRawCommand.UWord; +} + /** * Send an OpenLASIR frame with special NEC-style repeats. * There is NO delay after the last sent repeat! @@ -155,8 +187,24 @@ uint32_t IRsend::computeOpenLASIRRawDataAndChecksum(uint8_t aAddress, uint16_t a * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. */ void IRsend::sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth_P(&OpenLASIRProtocolConstants, - computeOpenLASIRRawDataAndChecksum(aAddress, aCommand), OPENLASIR_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, computeOpenLASIRRawDataAndChecksum(aAddress, aCommand), OPENLASIR_BITS, + aNumberOfRepeats); +} + +/** + * Send an OpenLASIR frame with special NEC-style repeats. + * There is NO delay after the last sent repeat! + * + * @param aAddress 8-bit address (Block ID). Only lower 8 bits are used. + * @param aDeviceID 8-bit Device ID. + * @param aMode 5-bit Mode. + * @param aData 3-bit Data (color, etc.). + * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + */ +void IRsend::sendOpenLASIR(uint8_t aAddress, uint8_t aDeviceID, uint8_t aMode, uint8_t aData, int_fast8_t aNumberOfRepeats) { + sendPulseDistanceWidth_P(&NECProtocolConstants, + computeOpenLASIRRawDataAndChecksum(aAddress, computeOpenLASIRRawCommand(aDeviceID, aMode, aData)), + OPENLASIR_BITS, aNumberOfRepeats); } /** @@ -165,7 +213,7 @@ void IRsend::sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNum * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. */ void IRsend::sendOpenLASIRRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth_P(&OpenLASIRProtocolConstants, aRawData, OPENLASIR_BITS, aNumberOfRepeats); + sendPulseDistanceWidth_P(&NECProtocolConstants, aRawData, OPENLASIR_BITS, aNumberOfRepeats); } /** @@ -204,8 +252,7 @@ bool IRrecv::decodeOpenLASIR() { // Check for repeat - here we have another header space length if (decodedIRData.rawlen == 4) { // Only claim this repeat if the last decoded protocol was OpenLASIR - if (lastDecodedProtocol == OPENLASIR - && matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) + if (lastDecodedProtocol == OPENLASIR && matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) && matchMark(irparams.rawbuf[3], NEC_BIT_MARK)) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; @@ -226,7 +273,7 @@ bool IRrecv::decodeOpenLASIR() { } // Decode the pulse distance data using NEC timing - decodePulseDistanceWidthData_P(&OpenLASIRProtocolConstants, OPENLASIR_BITS); + decodePulseDistanceWidthData_P(&NECProtocolConstants, OPENLASIR_BITS); // Success - now interpret the 32 raw bits LongUnion tValue; @@ -257,7 +304,7 @@ bool IRrecv::decodeOpenLASIR() { // Valid OpenLASIR frame decodedIRData.protocol = OPENLASIR; - decodedIRData.address = tValue.UByte.LowByte; // 8-bit validated address (Block ID) + decodedIRData.address = tValue.UByte.LowByte; // 8-bit validated address (Block ID) decodedIRData.command = tValue.UWord.HighWord; // 16-bit command (Device ID + Mode + Data) decodedIRData.numberOfBits = OPENLASIR_BITS; From eb24356026d7bdd8bca1d8b04975fac45666f6a8 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 16 Feb 2026 00:04:20 +0100 Subject: [PATCH 114/133] Fixed missing ESP IRAM_ATTR for receiving interrupt --- README.md | 5 +++-- changelog.md | 3 ++- src/IRReceive.hpp | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 160e96bc5..1a46bde62 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) - [Common issues when using IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-issues-when-using-irremote) - [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#migrating-legacy-projects-to-the-latest-version) - * [New features and changes in version 4.5](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-version-45) + * [New features and changes in version 4.6](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-version-46) * [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) @@ -128,7 +128,8 @@ See [this table](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme This library has been refactored, breaking backward compatibility with the old version, on which many examples on the Internet are based.
If your code uses `irrecv.decode(&results)`, it is written for Version 2.x. This library (Version 4.x) now uses a simpler `IrReceiver.decode()` syntax. See the Conversion guide below. -## New features and changes in version 4.5 +## New features and changes in version 4.6 +** Version 4.5.0 does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt.** - Support for **multiple receiver instances**.
`irparams_struct irparams` is now member of `IRrecv`. Thus `rawDataPtr` (pointer to irparams) was removed from `IrReceiver.decodedIRData`.
Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.rawbuf`, the same holds for `IrReceiver.irparams.rawlen`. diff --git a/changelog.md b/changelog.md index e03109626..708ec2d48 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,7 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master # 4.6.0 +- Fixed missing ESP IRAM_ATTR for receiving interrupt. - Changed USE_DEFAULT_FEEDBACK_LED_PIN from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. - Changed timer for ATtiny16X4. - Fixed missing initialization with pinMode() for feedback LED. @@ -10,7 +11,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Improved decodeSamsung(). - OpenLASIR protocol added by [danielweidman](https://github.com/danielweidman). -# 4.5.0 +# 4.5.0 - does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt. - Added support for multiple receiver instances. - irparams_struct irparams is now member of IRrecv. Thus removed rawDataPtr (pointer to irparams) from IrReceiver.decodedIRData. - Removed return value for all decodePulseDistanceWidthData() decoding functions, which returned a constant true. diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 9ba833405..05087c99c 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -278,6 +278,9 @@ void IRrecv::ReceiveInterruptHandler() { * 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 more than 2 IRrecv instances for receiving */ +#if defined(ESP8266) || defined(ESP32) +IRAM_ATTR +#endif void IRReceiveTimerInterruptHandler() { IrReceiver.ReceiveInterruptHandler(); #if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) From eb46c4e32ffc9e6cd57c481c61bf0dd69835fee6 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 16 Feb 2026 14:15:37 +0100 Subject: [PATCH 115/133] Documentation of Callback --- README.md | 29 +++++++--- .../CallbackDemo.ino} | 56 ++++++++++++------- .../PinDefinitionsAndMore.h | 0 examples/TinyReceiver/TinyReceiver.ino | 38 ++++++------- src/IRReceive.hpp | 17 +++--- src/TinyIRReceiver.hpp | 4 +- 6 files changed, 85 insertions(+), 59 deletions(-) rename examples/{SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino => CallbackDemo/CallbackDemo.ino} (72%) rename examples/{SimpleReceiverWithCallback => CallbackDemo}/PinDefinitionsAndMore.h (100%) diff --git a/README.md b/README.md index 1a46bde62..a50e6d6a8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [IRReceiver pinouts](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irreceiver-pinouts) - [Receiving IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-ir-codes) * [decodedIRData structure](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#decodedirdata-structure) + * [Callback functionality](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#callback-functionality) * [Ambiguous protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ambiguous-protocols) * [RAM usage of different protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ram-usage-of-different-protocols) * [Handling unknown Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#handling-unknown-protocols) @@ -73,7 +74,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) - * [Simulate an IR receiver module](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module) + * [Simulate an IR receiver module for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module-for-sending) * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency) * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol) - [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library) @@ -143,7 +144,7 @@ Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.ra - 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. -- **Callback** after receiving a command - It calls your code as soon as a message was received. +- **Callback** after receiving a command - It calls your code as soon as a frame was received. - Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. - New FAST protocol. - Automatic printout of the **corresponding send function** with `printIRSendUsage()`. @@ -467,6 +468,11 @@ The decoded values are the interpreted ones which are tolerant to such slight di IrReceiver.printIRSendUsage(&Serial); ``` +## Callback functionality +Sometimes it can be difficult to call decode() periodically in the main loop to avoid missing any IR frames. +In this case you can use the callback functionality as demonstrated in the [CallbackDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/CallbackDemo/CallbackDemo.ino#L136) example. +This enables you to perform `resume()` and short actions independently of the state of your main loop. + ## Ambiguous protocols ### NEC, Extended NEC, ONKYO, OpenLASIR The **NEC protocol** is defined as 8 bit address and 8 bit command. But the physical address and data fields are each 16 bit wide. @@ -647,12 +653,17 @@ For applications only requiring NEC, NEC variants or FAST -see below- protocol, 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.
+Unlike IRremote, which samples the input every 50 µs, the TinyReceiver receiver uses a **pin change interrupt** for on-the-fly decoding. +This restricts the range of protocols that can be recognised.
On each level change, the level and the time since the last change are used to incrementally decode the protocol.
With this operating principle, we **cannot wait for a timeout** and then decode the protocol as IRremote does.
-Instead, we need to know which is the last bit (level change) of a protocol 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). +Instead, we need to know which is the last bit (level change) of a protocol in order to perform the final decoding +and call of the optional **user-provided callback function** `handleReceivedTinyIRData()`.
+This means that **we need to know the number of bits in a protocol** and therefore the protocol family in order to decode successfully. + +For each complete IR frame/command received, the decoded data is copied to the `TinyIRReceiverData` structure +and the user-provided `handleReceivedTinyIRData()` function is called in an interrupt context. +However, **interrupts are explicitly enabled here** to allow the use of delay() and millis() etc. Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`. @@ -743,7 +754,7 @@ LED feedback is **always enabled** when sending and cannot be deactivated progra It can only be deactivated at compile time. # FAQ and hints -## Receiving stops after analogWrite() or tone() or after running a motor. +## Receiving stops after analogWrite() or tone() or after running a motor The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). On some boards where a software timer is available, the software timer is used.
Be aware that the hardware timer used for receiving should not be used for `analogWrite()`.
@@ -751,7 +762,7 @@ Especially **motor** control often uses the `analogWrite()` function and will th On the Uno and other AVR boards the receiver timer ist the same as the tone timer. Thus receiving will stop after a `tone()` command. See [ReceiveDemo example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/ReceiveDemo/ReceiveDemo.ino#L284-L298) how to deal with it, i.e. how to use `IrReceiver.restartTimer()`. -## Receiving sets overflow flag. +## Receiving sets overflow flag The flag `IRDATA_FLAGS_WAS_OVERFLOW` is set, if `RAW_BUFFER_LENGTH` is too small for all the marks and spaces of the protocol. This can happen on long protocol frames like the ones from air conditioner. It also can happen, if `RECORD_GAP_MICROS` is smaller than the real gap between a frame and the repetition frame, thus interpreting both as one consecutive frame. @@ -798,7 +809,7 @@ If you do not require more current than 20 mA, there is no need to use an extern On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:. -## Simulate an IR receiver module +## Simulate an IR receiver module for sending To simulate an IR receiver (such as the TSOP1738) which provides an active-low output, you only need to enable the `USE_NO_SEND_PWM` macro. In the case you must simulate exotic IR receivers, which provides an active-high output, you also need to enable the `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` macro. diff --git a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino b/examples/CallbackDemo/CallbackDemo.ino similarity index 72% rename from examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino rename to examples/CallbackDemo/CallbackDemo.ino index 5489dbc81..60ffe771a 100644 --- a/examples/SimpleReceiverWithCallback/SimpleReceiverWithCallback.ino +++ b/examples/CallbackDemo/CallbackDemo.ino @@ -1,14 +1,15 @@ /* - * SimpleReceiverWithCallback.cpp + * CallbackDemo.cpp * - * Demonstrates receiving NEC IR codes with IRrecv + * Demonstrates receiving NEC IR codes with IRrecv using callback function + * Based on SimpleReceiver example * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * ************************************************************************************ * MIT License * - * Copyright (c) 2022 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -67,12 +68,9 @@ #include /* - * For callback + * Callback specific variables and functions */ -#define PROCESS_IR_RESULT_IN_MAIN_LOOP -#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32) volatile bool sIRDataJustReceived = false; -#endif void ReceiveCompleteCallbackHandler(); void setup() { @@ -83,11 +81,17 @@ void setup() { // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); + + /* + * Tell the ISR to call this function, when a complete frame has been received + */ IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler); Serial.print(F("Ready to receive IR signals of protocols: ")); printActiveIRProtocols(&Serial); Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); + Serial.print(F("Using callback function for processing received data")); + } void loop() { @@ -95,15 +99,21 @@ void loop() { * Print in loop (interrupts are enabled here) if received data is available. */ if (sIRDataJustReceived) { - // Print a summary of received data + sIRDataJustReceived = false; + /* + * Print info of the received data + */ if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("Received noise or an unknown (or not yet enabled) protocol")); /* * We have an unknown protocol here, print more info. - * !!!Attention!!! This prints incorrect values, if we are late (not in this simple example :-)) - * and the the first mark of the next (repeat) data was yet received + * This will print incorrect timing values, if we are late (not in this simple example :-)) + * and the the first mark of the next (repeat) data was yet received. + * Therefore we first test for this condition. */ - IrReceiver.printIRResultRawFormatted(&Serial, true); // + if (!IrReceiver.isIdle()) { + IrReceiver.printIRResultRawFormatted(&Serial, true); + } } else { IrReceiver.printIRResultShort(&Serial); IrReceiver.printIRSendUsage(&Serial); @@ -115,19 +125,28 @@ void loop() { /* * Callback function * Here we know, that data is available. - * This function is executed in ISR (Interrupt Service Routine) context (interrupts are blocked here). - * Make it short and fast and keep in mind, that you can not use delay(), prints longer than print buffer size etc., - * because they require interrupts enabled to return. - * In order to enable other interrupts you can call sei() (enable interrupt again) after evaluating/copying data. - * Good practice, but somewhat more complex, is to copy relevant data and signal receiving to main loop. + * This function is executed in an ISR (Interrupt Service Routine) context. + * This means that interrupts are blocked here, so delay(), millis() and Serial prints of data longer than the print buffer size etc. will block forever. + * This is because they require their internal interrupt routines to run in order to return. + * Therefore it is best to make this callback function short and fast! + * A dirty hack is to enable interrupts again by calling sei() (enable interrupt again), but you should know what you are doing, + * + * A good practice -but somewhat more complex- is to perform small and time critical actions in the callback function, + * copy the relevant data to local variables and signal the receiving to main loop, which in turn processes this data. + * This is similar to simply using "if (IrReceiver.decode())", but has the advantage, + * that it does not block the receiving of the next IR frame, until the main loop reaches this statement. */ #if defined(ESP32) || defined(ESP8266) IRAM_ATTR # endif void ReceiveCompleteCallbackHandler() { - IrReceiver.decode(); // fill IrReceiver.decodedIRData /* - * Enable receiving of the next value. + * Fill IrReceiver.decodedIRData + */ + IrReceiver.decode(); + + /* + * Enable receiving of the next frame. */ IrReceiver.resume(); @@ -151,5 +170,4 @@ void ReceiveCompleteCallbackHandler() { * running in ISR (Interrupt Service Routine) context where interrupts are disabled. */ sIRDataJustReceived = true; - } diff --git a/examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h similarity index 100% rename from examples/SimpleReceiverWithCallback/PinDefinitionsAndMore.h rename to examples/CallbackDemo/PinDefinitionsAndMore.h diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 043caa907..1ab2b1e1a 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -4,19 +4,19 @@ * Small memory footprint and no timer usage! * * Receives IR protocol data of NEC protocol using pin change interrupts. - * On complete received IR command the function handleReceivedIRData(uint16_t aAddress, uint8_t aCommand, uint8_t aFlags) - * is called in Interrupt context but with interrupts being enabled to enable use of delay() etc. + * For each complete IR frame/command received, the decoded data is copied to the TinyIRReceiverData structure + * and the handleReceivedTinyIRData() function is called in an interrupt context. + * However, interrupts are explicitly enabled here to allow the use of delay() and millis() etc. * !!!!!!!!!!!!!!!!!!!!!! * Functions called in interrupt context should be running as short as possible, - * so if you require longer action, save the data (address + command) and handle it in the main loop. * !!!!!!!!!!!!!!!!!!!!! * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 - * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, - * leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. + * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command. + * This results in a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * @@ -26,7 +26,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,14 +71,6 @@ #include "TinyIRReceiver.hpp" // include the code -/* - * Helper macro for getting a macro definition as string - */ -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif - void setup() { Serial.begin(115200); @@ -111,7 +103,10 @@ void setup() { void loop() { if (TinyReceiverDecode()) { - + /* + * The library has already copied the data used for this output, + * so there is no need to do this in the callback function. + */ #if !defined(USE_FAST_PROTOCOL) // We have no address at FAST protocol Serial.print(F("Address=0x")); @@ -149,25 +144,28 @@ void loop() { #if defined(USE_CALLBACK_FOR_TINY_RECEIVER) /* * This is the function, which is called if a complete frame was received - * It runs in an ISR context with interrupts enabled, so functions like delay() etc. should work here + * This function is executed in an ISR (Interrupt Service Routine) context but with interrupts enabled! + * However, it is always best to keep this callback function short and fast! */ # if defined(ESP8266) || defined(ESP32) IRAM_ATTR # endif - void handleReceivedTinyIRData() { # if defined(ARDUINO_ARCH_MBED) || defined(ESP32) /* - * Printing is not allowed in ISR context for any kind of RTOS, so we use the slihjtly more complex, - * but recommended way for handling a callback :-). Copy data for main loop. + * Printing is not allowed in ISR context for RTOS based cores like ESP, even when interrupts are enabled. * For Mbed we get a kernel panic and "Error Message: Semaphore: 0x0, Not allowed in ISR context" for Serial.print() * for ESP32 we get a "Guru Meditation Error: Core 1 panic'ed" (we also have an RTOS running!) */ - // Do something useful here... # else // As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon printTinyReceiverResultMinimal(&Serial); # endif + if (TinyIRReceiverData.Command == 0x10) { + // do something SHORT here + } else if (TinyIRReceiverData.Command == 0x11) { + // do something SHORT here too + } } #endif diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 05087c99c..4e035bbb6 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -491,14 +491,6 @@ void IRrecv::end() { stop(); } -/** - * Returns status of reception - * @return true if no reception is on-going. - */ -bool IRrecv::isIdle() { - return (irparams.StateForISR == IR_REC_STATE_IDLE || irparams.StateForISR == IR_REC_STATE_STOP) ? true : false; -} - /** * Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame. * Internal counting of gap timing is independent of StateForISR and therefore independent of call time of resume(). @@ -540,7 +532,14 @@ void IRrecv::initDecodedIRData() { } /** - * Returns true if IR receiver data is available. + * @return true if available() is true or IR receiver has not received a mark/signal since last resume(). + */ +bool IRrecv::isIdle() { + return (irparams.StateForISR == IR_REC_STATE_IDLE || available()); +} + +/** + * Returns true if IR receiver has received a complete IR frame (detected by timeout after last mark). */ bool IRrecv::available() { return (irparams.StateForISR == IR_REC_STATE_STOP); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 748df5b49..a8126d89b 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -108,7 +108,7 @@ //#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement. //#define _IR_TIMING_TEST_PIN 7 TinyIRReceiverStruct TinyIRReceiverControl; -volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; +volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; // The persistent copy of all IR data after receiving a complete frame. To be used by main program. /* * Set input pin and output pin definitions etc. @@ -378,7 +378,7 @@ void IRPinChangeInterruptHandler(void) { * The parameter size is dependent of the code variant used in order to save program memory. * We have 6 cases: 0, 8 bit or 16 bit address, each with 8 or 16 bit command */ -#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running! +#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled interrupts(); // enable interrupts, so delay() etc. works in callback #endif TinyIRReceiverData.justWritten = true; From a0604f6f53b1d1e53ec3c29f07208635b09c1618 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 19 Feb 2026 01:21:53 +0100 Subject: [PATCH 116/133] IRCommandDispatcher now part of library --- .github/workflows/LibraryBuild.yml | 7 + README.md | 93 +++++++- changelog.md | 70 +++--- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 2 +- examples/CallbackDemo/PinDefinitionsAndMore.h | 2 +- examples/ControlRelay/PinDefinitionsAndMore.h | 2 +- .../IRDispatcherDemo/DemoIRCommandMapping.h | 38 ++- .../IRDispatcherDemo/IRDispatcherDemo.ino | 99 +++----- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/MicroGirs/PinDefinitionsAndMore.h | 2 +- .../MultipleReceivers/MultipleReceivers.ino | 3 + .../MultipleReceivers/PinDefinitionsAndMore.h | 2 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 2 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 2 +- .../PinDefinitionsAndMore.h | 2 +- examples/SimpleSender/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 2 +- examples/TinyReceiver/TinyReceiver.ino | 2 - examples/TinySender/PinDefinitionsAndMore.h | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 2 +- library.properties | 2 +- .../IRCommandDispatcher.h | 0 .../IRCommandDispatcher.hpp | 216 ++++++++++++------ src/IRProtocol.h | 11 +- src/IRProtocol.hpp | 5 +- src/IRReceive.hpp | 103 ++------- src/IRremoteInt.h | 9 +- src/TinyIRReceiver.hpp | 28 +-- src/ir_RC5_RC6.hpp | 196 +++++++++++++--- src/private/IRTimer.hpp | 44 +++- 42 files changed, 614 insertions(+), 362 deletions(-) rename {examples/IRDispatcherDemo => src}/IRCommandDispatcher.h (100%) rename {examples/IRDispatcherDemo => src}/IRCommandDispatcher.hpp (66%) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index efeea7cab..e7f4b6349 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -80,6 +80,7 @@ jobs: - stm32duino:STM32F1:genericSTM32F103C - sandeepmistry:nRF5:BBCmicrobit - Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off,sercom4=include + - vega:riscv:aries_v3 # Specify parameters for each board. # With sketches-exclude you may exclude specific examples for a board. Use a comma separated list. @@ -318,6 +319,12 @@ jobs: build-properties: # the flags were put in compiler.cpp.extra_flags All: -DRAW_BUFFER_LENGTH=750 + - arduino-boards-fqbn: vega:riscv:aries_v3 + platform-url: https://gitlab.com/riscv-vega/vega-arduino/-/raw/main/package_vega_index.json + #sketches-exclude: AllProtocolsOnLCD,UnitTest,ReceiveAndSendDistanceWidth,ReceiveDemo,SimpleReceiverForHashCodes # No print(uint64_t,.) available + build-properties: # the flags were put in compiler.cpp.extra_flags + All: -DF_CPU=100000000LL -DVEGA_ARIES_V3 -DRAW_BUFFER_LENGTH=750 + # fail-fast: false # false -> do not cancel all jobs / architectures if one job fails steps: diff --git a/README.md b/README.md index a50e6d6a8..c85a2deb4 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [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) +- [IRCommandDispatcher class](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ircommanddispatcher-class) - [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) - [Feedback LED](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#feedback-led) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) @@ -81,8 +82,11 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr - [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) +- [Compile options / macros for IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#compile-options--macros-for-irremote) +- [Macros for TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#macros-for-tinyir) +- [Macros for IRCommandDispatcher](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#macros-for-ircommanddispatcher) + [Changing include (*.h) files with Arduino IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#changing-include-h-files-with-arduino-ide) + + [Modifying compile options / macros with PlatformIO](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-platformio) + [Modifying compile options with Sloeber IDE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) - [Supported Boards](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-boards) - [Timer and pin usage](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage) @@ -109,7 +113,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr ` Hash `,     ` Pronto ` -` BoseWave `,     ` Bang & Olufsen `,     ` Lego `,     ` FAST `,     ` Whynter `,     ` MagiQuest `,     ` Velux `,     ` OpenLASIR ` +` BoseWave `,     ` Bang & Olufsen `,     ` Lego `,     ` FAST `,     ` Whynter `,     ` Marantz `,     ` MagiQuest `,     ` Velux `,     ` OpenLASIR ` Protocols can be switched off and on by defining macros before the line `#include ` like [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33): @@ -470,7 +474,7 @@ IrReceiver.printIRSendUsage(&Serial); ## Callback functionality Sometimes it can be difficult to call decode() periodically in the main loop to avoid missing any IR frames. -In this case you can use the callback functionality as demonstrated in the [CallbackDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/CallbackDemo/CallbackDemo.ino#L136) example. +In this case you can use the callback functionality as demonstrated in the [CallbackDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/CallbackDemo/CallbackDemo.ino#L126) example. This enables you to perform `resume()` and short actions independently of the state of your main loop. ## Ambiguous protocols @@ -647,6 +651,65 @@ http://www.harctoolbox.org/IR-resources.html
+# IRCommandDispatcher class +If you want to **handle many IR commands** in a structured way, you can use a big **switch statement**, or use the class `IRCommandDispatcher`.
+The IRCommandDispatcher class receives IR commands and maps them to different functions by means of a mapping array `IRMapping[]`. + +By default, every mapped command is **blocking**. However it can be declared as **non-blocking** and / or **repeatable**.
+Non-blocking commands are executed immediately, blocking commands are executed if no other command is just running. +If another blocking command is currently running, a **request to stop** is set +and the command is stored for the main loop to be executed by `checkAndRunSuspendedBlockingCommands()`. +The request to stop must be checked by any blocking function using the macros `DELAY_AND_RETURN_IF_STOP()`, `RETURN_IF_STOP`, `BREAK_IF_STOP` and `IS_STOP_REQUESTED`.
+Only commands that are marked as **repeatable** will be exectuted when a IR repeat frame is received. +Therefore this only makes sense for non-blocking comands :-). + +Code snippets are from [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo). + +```c++ +// IR code mapping which is useful if more than one remote is supported +#define IR_0 0x19 +#define IR_HASH 0x0D +#define COMMAND_BLINK IR_0 +#define COMMAND_STOP IR_HASH + +// Strings of commands for Serial output +static const char blink20times[] PROGMEM ="blink 20 times"; +static const char stop[] PROGMEM ="stop"; + +/* + * Main mapping array of commands to C functions and command strings + */ +const struct IRToCommandMappingStruct IRMapping[] = { +{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, blink20times }, +{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop }, +/* + * Short commands that can always be executed + */ +{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 }, +... +/* + * Repeatable short commands + */ +{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, +... + +/* + * This is a blocking function which checks for stop + */ +void doLedBlink20times() { + for (int i = 0; i < 20; ++i) { + digitalWrite(LED_BUILTIN, HIGH); + DELAY_AND_RETURN_IF_STOP(200); + digitalWrite(LED_BUILTIN, LOW); + DELAY_AND_RETURN_IF_STOP(200); + } +} +// Other useful macros are RETURN_IF_STOP, BREAK_IF_STOP and IS_STOP_REQUESTED. +``` + +Examples of mapping arrays can be found in the [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/DemoIRCommandMapping.h#L185), for [QuadrupedControl](https://github.com/ArminJo/QuadrupedControl/blob/master/examples/QuadrupedControl/QuadrupedIRCommandMapping.h#L445), for [RobotArmControl](https://github.com/ArminJo/RobotArmControl/blob/master/RobotArmControl/RobotArmIRCommandMapping.h#L320) or for [4 WD RobotCar control](https://github.com/ArminJo/PWMMotorControl/blob/master/examples/IRDispatcherControl/RobotCarIRCommandMapping.h#L308)
+ +
# Tiny NEC receiver and sender For applications only requiring NEC, NEC variants or FAST -see below- protocol, there is a special receiver / sender included, @@ -889,7 +952,7 @@ Serves as a IR **remote macro expander**. Receives Samsung32 protocol and on rec This serves as a **Netflix-key emulation** for my old Samsung H5273 TV. #### [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. +**Calling different functions** of your program for different IR codes. #### [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. @@ -944,7 +1007,7 @@ IR_RobotCar with TL1838 IR receiver plugged into expansion board.

-# Compile options / macros for this library +# Compile options / macros for IRremote To customize the library to different requirements, there are some compile options / macros available.
These macros must be defined in your program **before** the line `#include ` to take effect.
Modify them by enabling / disabling them, or change the values if applicable. @@ -979,7 +1042,8 @@ Modify them by enabling / disabling them, or change the values if applicable. | `DEBUG` | disabled | Enables lots of lovely debug output. | | `IR_USE_AVR_TIMER*` | | Selection of timer to be used for generating IR receiving sample interval. | -These next macros for **TinyIRReceiver** must be defined in your program before the line `#include ` to take effect. +# Macros for TinyIR +These macros must be defined in your program before the line `#include ` to take effect. | Name | Default value | Description | |-|-:|-| | `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. Not used in IRremote. | @@ -988,16 +1052,23 @@ These next macros for **TinyIRReceiver** must be defined in your program before | `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_EXTENDED_NEC_PROTOCOL` | disabled | Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. || `USE_ONKYO_PROTOCOL` | disabled | Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. | | `USE_FAST_PROTOCOL` | disabled | Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. | | `ENABLE_NEC2_REPEATS` | disabled | Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. | | `USE_CALLBACK_FOR_TINY_RECEIVER` | disabled | Call the user provided function `void handleReceivedTinyIRData()` each time a frame or repeat is received. | -The next macro for **IRCommandDispatcher** must be defined in your program before the line `#include ` to take effect. +
+ +# Macros for IRCommandDispatcher +These macros must be defined in your program before the line `#include ` to take effect. +| Name | Default value | Description | +|-|-:|-| | `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. | | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 4 bytes RAM + 1 byte RAM per mapping entry. | -| `BUZZER_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | +| `IR_ADDRESS` | empty | If set, compare the address returned by the IR library with this value before executing a command. | +| `DISPATCHER_BUZZER_FEEDBACK_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | + +
### Changing include (*.h) files with Arduino IDE First, use *Sketch > Show Sketch Folder (Ctrl+K)*.
@@ -1040,7 +1111,7 @@ Digispark boards are tested only with [ATTinyCore](https://github.com/SpenceKond - Nano Every, Uno WiFi Rev2, nRF5 BBC MicroBit, Nano33_BLE - BluePill with STM32 - RP2040 based boards (Raspberry Pi Pico, Nano RP2040 Connect etc.) - +- Indian VEGA RISC-V boards - not tested We are open to suggestions for adding support to new boards, however we highly recommend you contact your supplier first and ask them to provide support from their side.
diff --git a/changelog.md b/changelog.md index 708ec2d48..67b4a8e2e 100644 --- a/changelog.md +++ b/changelog.md @@ -4,59 +4,61 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.6.0 - Fixed missing ESP IRAM_ATTR for receiving interrupt. -- Changed USE_DEFAULT_FEEDBACK_LED_PIN from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. -- Changed timer for ATtiny16X4. -- Fixed missing initialization with pinMode() for feedback LED. -- Fixed bitmask error in sendBiphaseData() when not sending start bit. -- Improved decodeSamsung(). -- OpenLASIR protocol added by [danielweidman](https://github.com/danielweidman). +- Changed `USE_DEFAULT_FEEDBACK_LED_PIN` from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. +- Changed timer for **ATtiny16X4**. +- Fixed missing initialization with `pinMode()` for feedback LED. +- Fixed bitmask error in `sendBiphaseData()` when not sending start bit. +- Improved `decodeSamsung()`. +- `OpenLASIR` protocol added by [danielweidman](https://github.com/danielweidman). +- Added `DECODE_MARANTZ` and swapped parameter aMarantzExtension and aNumberOfRepeats of `sendMaranz()` to be consistent with other extensions. +- Moved `IRCommandDispatcher` from demo to main library folder. # 4.5.0 - does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt. -- Added support for multiple receiver instances. -- irparams_struct irparams is now member of IRrecv. Thus removed rawDataPtr (pointer to irparams) from IrReceiver.decodedIRData. -- Removed return value for all decodePulseDistanceWidthData() decoding functions, which returned a constant true. -- Removed parameter aEnableLEDFeedback in function IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) and IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin). -- LED feedback is always enabled for sending. It can only be disabled by using the macro NO_LED_SEND_FEEDBACK_CODE. -- Added output for UNKNOWN protocol to printIRSendUsage(). -- Added experimental sendVelux(). -- Added sendMaranz(). +- Added support for **multiple receiver instances**. +- irparams_struct `irparams` is now member of IRrecv. Thus removed `rawDataPt`r (pointer to irparams) from `IrReceiver.decodedIRData`. +- Removed return value for all `decodePulseDistanceWidthData()` decoding functions, which returned a constant true. +- Removed parameter `aEnableLEDFeedback` in function `IRsend::begin(bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)` and `IRsend::begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin)`. +- **LED feedback is always enabled for sending**. It can only be disabled by using the macro `NO_LED_SEND_FEEDBACK_CODE`. +- Added output for UNKNOWN protocol to `printIRSendUsage()`. +- Added experimental `sendVelux()`. +- Added `sendMaranz()`. - Fixed bug in ReceiveDemo.cpp if DEBUG_BUTTON_PIN is not defined. #1306. - Fixed minor bugs in Denon decoder. - Minor bug fixes for DEBUG. -- New handling of MARK_EXCESS_MICROS without strange rounding inconsistency. +- New handling of `MARK_EXCESS_MICROS` without strange rounding inconsistency. - Added experimental threshold decoding. # 4.4.3 -- Added USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN to make the software aware of send LED connected between VCC and send pin. -- Fixed backward compatibility bug for printIRResultShort(3 params). +- Added `USE_ACTIVE_LOW_OUTPUT_FOR_SEND_PIN` to make the software aware of send LED connected between VCC and send pin. +- Fixed backward compatibility bug for `printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros)`. - Minor improvements. # 4.4.2 -- Support for SAMD51 timer3 if timer 5 is not available (Adafruit ItsyBitsy M4). -- attachInterrupt() on SAMD has a different semantic :-(. See: https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/. +- 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. +- 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(). +- 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. +- Support for **ESP core 3.x** by akellai. +- `restartTimer()` now uses variable sMicrosAtLastStopTimer to keep track of uncounted ticks between stopTimer() and restartTimer(). +- **Removed functions** addTicksToInternalTickCounter() and addMicrosToInternalTickCounter(), which were added in 4.1.0. +- Version 2.2.0 of TinyIR with new `TinyReceiverDecode()` function to be used as **drop in for IrReceiver.decode()**. +- Support of `RC6A`. # 4.4.0 - Using 8 bit raw timing buffer for all timings except frame gap (former rawbuf[0]). -- Renamed decodedIRData.initialGap to decodedIRData.initialGapTicks. -- sendNEC() and sendNEC2() now accepts 16 bit command to better map to NECext protocol found in IRDB databases. -- ir_DistanceWidthProtocol() now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. -- Improved sensitivity and decoding of PULSE_DISTANCE + PULSE_WIDTH protocols. -- Changed TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING to TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT. +- Renamed `decodedIRData.initialGap` to `decodedIRData.initialGapTicks`. +- `sendNEC()` and `sendNEC2()` now **accepts 16 bit command** to better map to **NECext protocol** found in IRDB databases. +- `ir_DistanceWidthProtocol()` now decodes up to 10 ms mark or spaces if RAM is bigger than 2 k. +- Improved sensitivity and decoding of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. +- Changed `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING` to `TOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT`. - Improved examples AllProtocolsOnLCD, UnitTest and SimpleReceiver. -- New functions decodePulseDistanceWidthData() with 6 parameters and decodePulseDistanceWidthDataStrict() with 7 parameters. +- New functions `decodePulseDistanceWidthData()` with 6 parameters and `decodePulseDistanceWidthDataStrict()` with 7 parameters. # 4.3.2 - Added sendSonyMSB(unsigned long data, int nbits) as a clone of sendSony(unsigned long data, int nbits) to be more consistent. diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/CallbackDemo/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/CallbackDemo/PinDefinitionsAndMore.h +++ b/examples/CallbackDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/IRDispatcherDemo/DemoIRCommandMapping.h b/examples/IRDispatcherDemo/DemoIRCommandMapping.h index 26110da23..929eafdf7 100644 --- a/examples/IRDispatcherDemo/DemoIRCommandMapping.h +++ b/examples/IRDispatcherDemo/DemoIRCommandMapping.h @@ -1,26 +1,43 @@ /* * DemoIRCommandMapping.h * - * IR remote button codes, strings, and functions to call + * Contains IR remote button codes, strings, and the mapping of codes to functions to call by the dispatcher * - * Copyright (C) 2019-2022 Armin Joachimsmeyer + * Copyright (C) 2019-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * + * This file is part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. + * + * IRMP is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ #ifndef _IR_COMMAND_MAPPING_H #define _IR_COMMAND_MAPPING_H #include -//#include "Commands.h" // includes all the commands used in the mapping arrays below + +#include "IRCommandDispatcher.h" // IRToCommandMappingStruct, IR_COMMAND_FLAG_BLOCKING etc. are defined here /* * !!! Choose your remote !!! */ -//#define USE_KEYES_REMOTE_CLONE With number pad and direction control switched, will be taken as default +//#define USE_KEYES_REMOTE_CLONE With number pad and direction control swapped, will be taken as default //#define USE_KEYES_REMOTE #if !defined(USE_KEYES_REMOTE) && !defined(USE_KEYES_REMOTE_CLONE) -#define USE_KEYES_REMOTE_CLONE // the one you can buy at aliexpress +#define USE_KEYES_REMOTE_CLONE // the one you can buy at Aliexpress #endif #if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE)) @@ -144,7 +161,7 @@ * Main mapping of commands to C functions */ -// IR strings of functions for output +// Strings of commands for Serial output static const char LEDon[] PROGMEM ="LED on"; static const char LEDoff[] PROGMEM ="LED off"; @@ -164,20 +181,19 @@ static const char stop[] PROGMEM ="stop"; // not used yet static const char test[] PROGMEM ="test"; static const char pattern[] PROGMEM ="pattern"; -static const char unknown[] PROGMEM ="unknown"; /* * Main mapping array of commands to C functions and command strings */ const struct IRToCommandMappingStruct IRMapping[] = { /**/ -{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING, &doLedBlink20times, blink20times }, /**/ +{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, blink20times }, /**/ { COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop }, /* - * Short commands, which can be executed always + * Short commands that can always be executed */ -{ COMMAND_TONE1, IR_COMMAND_FLAG_BLOCKING, &doTone1800, tone1800 }, /**/ -{ COMMAND_TONE3, IR_COMMAND_FLAG_BLOCKING, &doPrintMenu, printMenu }, /**/ +{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 }, /**/ +{ COMMAND_TONE3, IR_COMMAND_FLAG_NON_BLOCKING, &doPrintMenu, printMenu }, /**/ { COMMAND_ON, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOn, LEDon }, /**/ { COMMAND_OFF, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOff, LEDoff }, /**/ { COMMAND_START, IR_COMMAND_FLAG_NON_BLOCKING, &doLedBlinkStart, blinkStart }, /**/ diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index b64086ecb..cf4228254 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -1,9 +1,9 @@ /* * IRDispatcherDemo.cpp * - * Receives NEC IR commands and maps them to different actions by means of a mapping array. + * Example how to use IRCommandDispatcher to receive IR commands and map them to different actions / functions by means of a mapping array. * - * Copyright (C) 2020-2021 Armin Joachimsmeyer + * Copyright (C) 2020-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRMP https://github.com/IRMP-org/IRMP. @@ -29,57 +29,32 @@ /* * Choose the library to be used for IR receiving */ -#define USE_TINY_IR_RECEIVER // Recommended, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding -//#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Requires additional 112 bytes program memory + 4 bytes RAM - -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -// Some kind of auto detect library if USE_TINY_IR_RECEIVER is deactivated -#if !defined(USE_TINY_IR_RECEIVER) -# if defined(IR_RECEIVE_PIN) -#define USE_TINY_IR_RECEIVER -# elif !defined(USE_IRMP_LIBRARY) && defined(IRMP_INPUT_PIN) -#define USE_IRMP_LIBRARY -# else -#error No IR library selected -# endif -#endif - -//#define NO_LED_FEEDBACK_CODE // You can set it here, before the include of IRCommandDispatcher below - -#if defined(USE_TINY_IR_RECEIVER) +//#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding +//#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding +//#define USE_IRMP_LIBRARY // The IRMP library is used for decoding //#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -#elif defined(USE_IRMP_LIBRARY) -/* - * IRMP version - */ -#define IR_RECEIVE_PIN 2 -#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used. -#if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) -#define FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN +#if defined(USE_TINY_IR_RECEIVER) && defined(TONE_PIN) +#define DISPATCHER_BUZZER_FEEDBACK_PIN TONE_PIN // The pin to be used for the optional 50 ms buzzer feedback before executing a command. Only available for TinyIR. #endif -//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory - -#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some program memory. Must before #include - +#if defined(USE_IRMP_LIBRARY) +//Enable protocols for IRMP #define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol //#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 +//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory -# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) -#define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN -# endif -/* - * After setting the definitions we can include the code and compile it. - */ -#include -void handleReceivedIRData(); void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration); -#endif // #if defined(USE_IRMP_LIBRARY) +#endif // defined(USE_IRMP_LIBRARY) bool doBlink = false; uint16_t sBlinkDelay = 200; +/* + * The functions which are called by the IR commands. + * They must be declared before including DemoIRCommandMapping.h, where the mapping to IR keys is defined. + */ void doPrintMenu(); void doLedOn(); void doLedOff(); @@ -93,19 +68,12 @@ void doTone1800(); void doTone2200(); /* - * Set definitions and include IRCommandDispatcher library after the declaration of all commands to map + * Set definitions and include IRCommandDispatcher library after the declaration of all commands required for mapping */ -#define INFO // to see some informative output -#include "IRCommandDispatcher.h" // Only for required declarations, the library itself is included below after the definitions of the commands -#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IR_ADDRESS and IRMapping and string "unknown". +#define INFO // to see some informative output of the IRCommandDispatcher library +#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IRMapping array, IR_ADDRESS etc. #include "IRCommandDispatcher.hpp" -// Helper macro for getting a macro definition as string -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) -#endif - void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); @@ -120,7 +88,7 @@ void setup() { // Just to know which program is running on my Arduino #if defined(USE_TINY_IR_RECEIVER) - Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver")); + Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver library version " VERSION_TINYIR)); #elif defined(USE_IRREMOTE_LIBRARY) Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRremote library version " VERSION_IRREMOTE)); #elif defined(USE_IRMP_LIBRARY) @@ -128,29 +96,14 @@ void setup() { #endif #if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) - // play feedback tone before setup, since it kills the IR timer settings + // play feedback tone before IRDispatcher.init(), because it kills the IR timer settings, which are made by init() tone(TONE_PIN, 1000, 50); delay(50); #endif - IRDispatcher.init(); // This just calls irmp_init() -#if defined(USE_TINY_IR_RECEIVER) - Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN))); -#else - irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp + IRDispatcher.init(); // This calls the init function of the chosen library + IRDispatcher.printIRInfo(&Serial); - Serial.print(F("Ready to receive IR signals of protocols: ")); - irmp_print_active_protocols(&Serial); - Serial.println(F("at pin " STR(IRMP_INPUT_PIN))); - -# if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) - irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN - Serial.println(F("IR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN))); -# endif -#endif - - Serial.print(F("Listening to commands of IR remote of type ")); - Serial.println(IR_REMOTE_NAME); doPrintMenu(); } @@ -174,6 +127,9 @@ void loop() { // delay(10); } +/* + * Menu for simple China Keyes or Keyes clone IR controls with number pad and direction control pad + */ void doPrintMenu() { Serial.println(); Serial.println(F("Press 1 for tone 1800 Hz")); @@ -221,7 +177,7 @@ void doLedBlinkStart() { doBlink = true; } /* - * This is a blocking function and checks periodically for stop + * This is a blocking function which checks for stop */ void doLedBlink20times() { for (int i = 0; i < 20; ++i) { @@ -253,6 +209,7 @@ void doTone2200() { /* * Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated * It currently disables the receiving of repeats + * It is not part of the library because it statically allocates the tone interrupt vector 7. */ void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) { # if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index 3792296ae..3340d0fe9 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -148,6 +148,9 @@ void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance) { * Here we just call the standard ReceiveInterruptHandler for the second receiver. * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving. */ +#if defined(ESP8266) || defined(ESP32) +IRAM_ATTR +#endif void UserIRReceiveTimerInterruptHandler() { MySecondIrReceiver.ReceiveInterruptHandler(); } diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 1ab2b1e1a..84f75b81a 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -58,7 +58,6 @@ /* * Protocol selection */ -//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. @@ -68,7 +67,6 @@ */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received. - #include "TinyIRReceiver.hpp" // include the code void setup() { diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index fc89e0a96..b3d71d11a 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -341,7 +341,7 @@ void noTone(uint8_t aPinNumber){ #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. +#warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 diff --git a/library.properties b/library.properties index 22a7127f9..0289b475f 100644 --- a/library.properties +++ b/library.properties @@ -6,5 +6,5 @@ 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, 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 +architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno,riscv includes=IRremote.hpp diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.h b/src/IRCommandDispatcher.h similarity index 100% rename from examples/IRDispatcherDemo/IRCommandDispatcher.h rename to src/IRCommandDispatcher.h diff --git a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp similarity index 66% rename from examples/IRDispatcherDemo/IRCommandDispatcher.hpp rename to src/IRCommandDispatcher.hpp index dd5857add..3f3971bac 100644 --- a/examples/IRDispatcherDemo/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -11,7 +11,7 @@ * A blocking command is stored and sets a stop flag for an already running blocking function to terminate. * The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands(). * - * Copyright (C) 2019-2024 Armin Joachimsmeyer + * Copyright (C) 2019-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. @@ -46,9 +46,11 @@ #include "IRCommandDispatcher.h" -#if !defined(STR_HELPER) && !defined(STR) -#define STR_HELPER(x) #x -#define STR(x) STR_HELPER(x) +//#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding +//#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding +//#define USE_IRMP_LIBRARY // The IRMP library is used for decoding +#if !defined(USE_TINY_IR_RECEIVER) && !defined(USE_IRREMOTE_LIBRARY) && !defined(USE_IRMP_LIBRARY) +#define USE_TINY_IR_RECEIVER // Set TiniIR as default library #endif /* * Enable this to see information on each call. @@ -78,27 +80,21 @@ IRCommandDispatcher IRDispatcher; #endif #if defined(USE_TINY_IR_RECEIVER) -#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 +/****************************** + * Code for the TinyIR library + ******************************/ +#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the function "handleReceivedTinyIRData()" below each time a frame or repeat is received. +#include "TinyIRReceiver.hpp" // included in "IRremote" and "IRMP" library void IRCommandDispatcher::init() { initPCIInterruptForTinyReceiver(); } - -/* - * @return true, if IR Receiver is attached - */ -void IRCommandDispatcher::printIRInfo(Print *aSerial) { - aSerial->println(); - // For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h - aSerial->print(F("Listening to IR remote of type ")); - aSerial->print(IR_REMOTE_NAME); - aSerial->println(F(" at pin " STR(IR_RECEIVE_PIN))); -} - /* - * This is the TinyReceiver callback function, which is called if a complete command was received - * It checks for right address and then call the dispatcher + * This is the TinyReceiver callback function, which is called if a complete command was received. + * Interrupts are enabled here to allow e.g. delay() in commands. + * Copy the (volatile) IR data in order not to be overwritten on receiving of next frame. + * Next, check for right address if IR_ADDRESS is defined. + * At last call the dispatcher. */ # if defined(ESP8266) || defined(ESP32) IRAM_ATTR @@ -113,8 +109,16 @@ void handleReceivedTinyIRData() { printTinyReceiverResultMinimal(&Serial); # endif - if (TinyIRReceiverData.Address == IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h +# if defined(IR_ADDRESS) + // if available, compare address + if (TinyIRReceiverData.Address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h + CD_INFO_PRINT(F("Wrong address. Expected 0x")); + CD_INFO_PRINTLN(IR_ADDRESS, HEX); + } else +# endif + { IRDispatcher.IRReceivedData.isAvailable = true; + // check if dispatcher enabled if(!IRDispatcher.doNotUseDispatcher) { /* * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, @@ -122,29 +126,36 @@ void handleReceivedTinyIRData() { */ IRDispatcher.checkAndCallCommand(false); } - - } else { - CD_INFO_PRINT(F("Wrong address. Expected 0x")); - CD_INFO_PRINTLN(IR_ADDRESS, HEX); } } #elif defined(USE_IRMP_LIBRARY) -# if !defined(IRMP_USE_COMPLETE_CALLBACK) -# error IRMP_USE_COMPLETE_CALLBACK must be activated for IRMP library -# endif - -void IRCommandDispatcher::init() { +/****************************** + * Code for the IRMP library + ******************************/ +#define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used. +#define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings for printIRInfo() +#include "irmp.hpp" +void handleReceivedIRData(); + +void IRCommandDispatcher::init() +{ irmp_init(); + irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp } /* - * This is the callback function, which is called if a complete command was received + * This is the callback function, which is called if a complete command was received. + * Interrupts are NOT enabled here so we must do it manually to allow e.g. delay() in commands. + * Copy the (volatile) IR data in order not to be overwritten on receiving of next frame. + * Next, check for right address if IR_ADDRESS is defined. + * At last call the dispatcher. */ #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif -void handleReceivedIRData() { +void handleReceivedIRData() +{ IRMP_DATA tTeporaryData; irmp_get_data(&tTeporaryData); IRDispatcher.IRReceivedData.address = tTeporaryData.address; @@ -152,46 +163,90 @@ void handleReceivedIRData() { IRDispatcher.IRReceivedData.isRepeat = tTeporaryData.flags & IRMP_FLAG_REPETITION; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); +#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled + interrupts(); // To enable delay() for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. +# endif + CD_INFO_PRINT(F("A=0x")); CD_INFO_PRINT(IRDispatcher.IRReceivedData.address, HEX); CD_INFO_PRINT(F(" C=0x")); CD_INFO_PRINT(IRDispatcher.IRReceivedData.command, HEX); - if (IRDispatcher.IRReceivedData.isRepeat) { + if (IRDispatcher.IRReceivedData.isRepeat) + { CD_INFO_PRINT(F("R")); } CD_INFO_PRINTLN(); - // To enable delay() for commands -# if !defined(ARDUINO_ARCH_MBED) - interrupts(); // be careful with always executable commands which lasts longer than the IR repeat duration. -# endif - - if (IRDispatcher.IRReceivedData.address == IR_ADDRESS) { - IRDispatcher.checkAndCallCommand(true); - } else { +# if defined(IR_ADDRESS) + // if available, compare address + if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { CD_INFO_PRINT(F("Wrong address. Expected 0x")); CD_INFO_PRINTLN(IR_ADDRESS, HEX); + } else +# endif + { + IRDispatcher.IRReceivedData.isAvailable = true; + // check if dispatcher enabled + if (!IRDispatcher.doNotUseDispatcher) + { + /* + * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, + * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() + */ + IRDispatcher.checkAndCallCommand(false); + } } } #endif // elif defined(USE_IRMP_LIBRARY) +/******************************************* + * Start of the IR library independent code + *******************************************/ +void IRCommandDispatcher::printIRInfo(Print *aSerial) +{ + aSerial->println(); + // For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h +#if defined(USE_IRMP_LIBRARY) +# if defined(IR_REMOTE_NAME) + aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IRMP_INPUT_PIN))); +# else + aSerial->println(F("Listening to IR remote at pin " STR(IRMP_INPUT_PIN))); +# endif + Serial.print(F("Accepted protocols are: ")); + irmp_print_active_protocols(&Serial); + Serial.println(); +#else +# if defined(IR_REMOTE_NAME) + aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IR_RECEIVE_PIN))); +# else + aSerial->println(F("Listening to IR remote at pin " STR(IR_RECEIVE_PIN))); +# endif +#endif +} + /* * The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands() - * Non blocking commands are executed directly, blocking commands are executed if enabled by parameter and no other command is just running. - * Otherwise request to stop (requestToStopReceived) is set and command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands(). - * Sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived - * @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. Should be false if called by ISR in order not to block ISR. + * Non blocking commands are executed immediately, blocking commands are executed if no other command is just running. + * If another blocking command is currently running, the request to stop is set + * and the command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands(). + * This function sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived + * @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. + * Should be false if called by ISR in order not to block ISR. Is true when called from checkAndRunSuspendedBlockingCommands(). */ -void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) { - if (IRReceivedData.command == COMMAND_EMPTY) { +void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) +{ + if (IRReceivedData.command == COMMAND_EMPTY) + { return; } /* * Search for command in Array of IRToCommandMappingStruct */ - for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { - if (IRReceivedData.command == IRMapping[i].IRCode) { + for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) + { + if (IRReceivedData.command == IRMapping[i].IRCode) + { /* * Command found */ @@ -201,7 +256,8 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate /* * Check for repeat and if repeat is allowed for the current command */ - if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) { + if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) + { #if defined(LOCAL_DEBUG) Serial.print(F("Repeats of command \"")); Serial.print(tCommandName); @@ -213,7 +269,8 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate /* * Do not accept recursive call of the same command */ - if (currentBlockingCommandCalled == IRReceivedData.command) { + if (currentBlockingCommandCalled == IRReceivedData.command) + { #if defined(LOCAL_DEBUG) Serial.print(F("Recursive command \"")); Serial.print(tCommandName); @@ -226,24 +283,28 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate * Execute commands */ bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING); - if (tIsNonBlockingCommand) { + if (tIsNonBlockingCommand) + { // short command here, just call CD_INFO_PRINT(F("Run non blocking command: ")); CD_INFO_PRINTLN(tCommandName); -#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER) +#if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* * Do (non blocking) buzzer feedback before command is executed */ if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { - tone(BUZZER_PIN, 2200, 50); + tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50); } #endif IRMapping[i].CommandToCall(); - } else { + } + else + { /* * Blocking command here */ - if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) { + if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) + { /* * Here no blocking command was running and we are called from main loop */ @@ -251,18 +312,19 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate justCalledBlockingCommand = true; currentBlockingCommandCalled = IRReceivedData.command; // set lock for recursive calls lastBlockingCommandCalled = IRReceivedData.command; // set history, can be evaluated by main loop + /* * This call is blocking!!! */ CD_INFO_PRINT(F("Run blocking command: ")); CD_INFO_PRINTLN(tCommandName); -#if defined(BUZZER_PIN) && defined(USE_TINY_IR_RECEIVER) +#if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* * Do (non blocking) buzzer feedback before command is executed */ if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { - tone(BUZZER_PIN, 2200, 50); + tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50); } #endif @@ -271,7 +333,9 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate Serial.println(F("End of blocking command")); #endif currentBlockingCommandCalled = COMMAND_EMPTY; - } else { + } + else + { /* * Called by ISR or another command still running. * Do not run command directly, but set request to stop to true and store command @@ -294,11 +358,13 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate * Intended to be called from main loop * @return true, if command was called */ -bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { +bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() +{ /* * Take last rejected command and call associated function */ - if (BlockingCommandToRunNext != COMMAND_EMPTY) { + if (BlockingCommandToRunNext != COMMAND_EMPTY) + { CD_INFO_PRINT(F("Run stored command=0x")); CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX); @@ -321,7 +387,7 @@ void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunN #else void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext) #endif - { +{ CD_INFO_PRINT(F("Set next command to run to 0x")); CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX); BlockingCommandToRunNext = aBlockingCommandToRunNext; @@ -333,27 +399,35 @@ void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNe * To be used in blocking functions as delay * @return true - as soon as stop received */ -bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) { +bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) +{ uint32_t tStartMillis = millis(); - do { - if (requestToStopReceived) { + do + { + if (requestToStopReceived) + { return true; } - } while (millis() - tStartMillis < aDelayMillis); + } + while (millis() - tStartMillis < aDelayMillis); return false; } -void IRCommandDispatcher::printIRCommandString(Print *aSerial) { - for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { - if (IRReceivedData.command == IRMapping[i].IRCode) { +void IRCommandDispatcher::printIRCommandString(Print *aSerial) +{ + for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) + { + if (IRReceivedData.command == IRMapping[i].IRCode) + { aSerial->println(reinterpret_cast(IRMapping[i].CommandString)); return; } } - aSerial->println(reinterpret_cast(unknown)); + aSerial->println(F("unknown")); } -void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) { +void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) +{ requestToStopReceived = aRequestToStopReceived; } diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 1c0888414..4704ab895 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -50,7 +50,7 @@ || 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) \ +|| defined(DECODE_LEGO_PF) || defined(DECODE_MAGIQUEST) || defined(DECODE_WHYNTER) || defined(DECODE_MARANTZ) || defined(DECODE_FAST) \ || defined(DECODE_OPENLASIR))) /* * If no protocol is explicitly enabled, we enable all protocols @@ -71,6 +71,7 @@ #define DECODE_LEGO_PF #define DECODE_MAGIQUEST #define DECODE_WHYNTER +#define DECODE_MARANTZ #define DECODE_FAST #define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command # endif @@ -91,15 +92,15 @@ /** * An enum consisting of all supported formats. * You do NOT need to remove entries from this list when disabling protocols! - * !!!Must be the same order as ProtocolNames in IRReceive.hpp!!! + * !!!Must be the same order as ProtocolNames in IRProtocol.hpp!!! */ typedef enum { - UNKNOWN = 0, PULSE_WIDTH, PULSE_DISTANCE, APPLE, DENON, JVC, LG, LG2, NEC, NEC2, /* 10 NEC with full frame as repeat */ + UNKNOWN = 0, PULSE_WIDTH, PULSE_DISTANCE, APPLE, DENON, JVC, LG, LG2, NEC, NEC2, /* 10 entries */ ONKYO, PANASONIC, KASEIKYO, KASEIKYO_DENON, KASEIKYO_SHARP, KASEIKYO_JVC, KASEIKYO_MITSUBISHI, RC5, RC6, RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ - SAMSUNG, /* 20*/ + SAMSUNG, /* 11 entries */ SAMSUNGLG, SAMSUNG48, SHARP, SONY, /* Now the exotic protocols */ - BANG_OLUFSEN, BOSEWAVE, LEGO_PF, MAGIQUEST, WHYNTER, /* 30 */ + BANG_OLUFSEN, BOSEWAVE, LEGO_PF, MAGIQUEST, WHYNTER, MARANTZ,/* 10 entries */ FAST, OPENLASIR, OTHER } decode_type_t; extern const char *const ProtocolNames[]; // The array of name strings for the decode_type_t enum diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 77c04a529..72f6999e5 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -73,6 +73,7 @@ const char string_BoseWave[] PROGMEM = "BoseWave"; const char string_Lego[] PROGMEM = "Lego"; const char string_MagiQuest[] PROGMEM = "MagiQuest"; const char string_Whynter[] PROGMEM = "Whynter"; +const char string_Marantz[] PROGMEM = "Marantz"; const char string_FAST[] PROGMEM = "FAST"; const char string_OpenLASIR[] PROGMEM = "OpenLASIR"; const char string_Other[] PROGMEM = "OTHER"; @@ -86,8 +87,8 @@ PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Appl 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_OpenLASIR, - string_Other + , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_Marantz, string_FAST, + string_OpenLASIR, string_Other #endif }; diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 4e035bbb6..1fbb66725 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -616,8 +616,14 @@ bool IRrecv::decode() { } #endif -#if defined(DECODE_RC5) +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) +# if defined(DECODE_RC5) && !defined(DECODE_MARANTZ) IR_TRACE_PRINTLN(F("Attempting RC5 decode")); +# elif !defined(DECODE_RC5) && defined(DECODE_MARANTZ) + IR_TRACE_PRINTLN(F("Attempting Marantz decode")); +# else + IR_TRACE_PRINTLN(F("Attempting RC5 and Marantz decode")); +# endif if (decodeRC5()) { return true; } @@ -1132,78 +1138,6 @@ void IRrecv::decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset); } -/* - * Static variables for the getBiphaselevel function - */ -uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array -uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. -uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. -uint16_t sBiphaseTimeUnit; - -void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) { - sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset; - sBiphaseTimeUnit = aBiphaseTimeUnit; - sBiphaseUsedTimingIntervals = 0; -} - -/** - * Gets the level of one time interval (aBiphaseTimeUnit) at a time from the raw buffer. - * The RC5/6 decoding is easier if the data is broken into time intervals. - * E.g. if the buffer has mark for 2 time intervals and space for 1, - * successive calls to getBiphaselevel will return 1, 1, 0. - * - * _ _ _ _ _ _ _ _ _ _ _ _ _ - * _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge - * _ _ _ ___ _ ___ ___ _ - Mark - * Data _____| |___| |_| |_| |_| |___| |___| |_| | - Data starts with a mark->space bit - * 1 0 0 0 1 1 0 1 0 1 1 - Space - * A mark to space at a significant clock edge results in a 1 - * A space to mark at a significant clock edge results in a 0 (for RC6) - * Returns current level [MARK or SPACE] or -1 for error (measured time interval is not a multiple of sBiphaseTimeUnit). - */ -uint_fast8_t IRrecv::getBiphaselevel() { - uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK) - - if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawlen) { - return SPACE; // After end of recorded buffer, assume space. - } - - tLevelOfCurrentInterval = (sBiphaseDecodeRawbuffOffset) & 1; // on odd rawbuf offsets we have mark timings - - /* - * Setup data if sUsedTimingIntervals is 0 - */ - if (sBiphaseUsedTimingIntervals == 0) { - uint16_t tCurrentTimingWith = irparams.rawbuf[sBiphaseDecodeRawbuffOffset]; - uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS; - - if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 1; - } else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 2; - } else if (matchTicks(tCurrentTimingWith, (3 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 3; - } else { - return -1; - } - } - -// We use another interval from tCurrentTimingIntervals - sBiphaseUsedTimingIntervals++; - -// keep track of current timing offset - if (sBiphaseUsedTimingIntervals >= sBiphaseCurrentTimingIntervals) { - // we have used all intervals of current timing, switch to next timing value - sBiphaseUsedTimingIntervals = 0; - sBiphaseDecodeRawbuffOffset++; - } - - IR_TRACE_PRINTLN(tLevelOfCurrentInterval); - - return tLevelOfCurrentInterval; -} - /********************************************************************************************************************** * Internal Hash decode function **********************************************************************************************************************/ @@ -1983,6 +1917,10 @@ uint32_t IRrecv::getTotalDurationOfRawData() { // @formatter:off +void printNumberOfRepeats(Print *aSerial) { + aSerial->print(F(", ")); +} + /** * 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. @@ -2058,7 +1996,8 @@ void IRrecv::printIRSendUsage(Print *aSerial) { * (0x
, 0x, ); */ if (decodedIRData.protocol == UNKNOWN){ - aSerial->print(F("Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, , ")); + aSerial->print(F("Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, ")); + printNumberOfRepeats(aSerial); } #if defined(DECODE_DISTANCE_WIDTH) else if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH) { @@ -2092,7 +2031,9 @@ void IRrecv::printIRSendUsage(Print *aSerial) { } else { aSerial->print('L'); } - aSerial->print(F("SB_FIRST, , ")); + aSerial->print(F("SB_FIRST, ")); + printNumberOfRepeats(aSerial); + } #endif // defined(DECODE_DISTANCE_WIDTH) else { @@ -2121,16 +2062,18 @@ void IRrecv::printIRSendUsage(Print *aSerial) { aSerial->print(F(", 0x")); aSerial->print(decodedIRData.command, HEX); if (decodedIRData.protocol == SONY) { - aSerial->print(F(", 2, ")); + printNumberOfRepeats(aSerial); + aSerial->print(F(", ")); aSerial->print(decodedIRData.numberOfBits); } else { - aSerial->print(F(", ")); + printNumberOfRepeats(aSerial); + } } -#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 +#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6) || defined(DECODE_MARANTZ) + if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A || decodedIRData.protocol == MARANTZ)) { + // Vendor code, Customer or MarantzExtension parameter, which is after numberOfRepeats parameter aSerial->print(F(", 0x")); aSerial->print(decodedIRData.extra, HEX); } diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 9cab19717..ec598ebcb 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -35,8 +35,9 @@ #include -#define MARK 1 #define SPACE 0 +#define MARK 1 +#define NO_MARK_OR_SPACE 2 // Used as return value for getBiphaselevel() #if defined(PARTICLE) #define F_CPU 16000000 // definition for a board for which F_CPU is not defined @@ -662,7 +663,7 @@ 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, + void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aMarantzExtension, 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, @@ -719,8 +720,8 @@ class IRsend { sendNECMSB(aRawData, nbits); } void sendNECMSB(uint32_t data, uint8_t nbits, bool repeat = false); - void sendRC5(uint32_t data, uint8_t nbits); - void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle); + void sendRC5(uint32_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead.")));; + void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead.")));; void sendRC6Raw(uint32_t data, uint8_t nbits); void sendRC6(uint32_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC6Raw()."))); void sendRC6Raw(uint64_t data, uint8_t nbits); diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index a8126d89b..0c4790c36 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -28,7 +28,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -75,15 +75,14 @@ /* * Protocol selection */ -//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. -//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. +//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. +//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define IR_RECEIVE_PIN 2 -//#define 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 +//#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" @@ -146,7 +145,11 @@ volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; // The persistent || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\ || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \ ) -#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change. +/* + * Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change. + * Requires additional 112 bytes program memory + 4 bytes RAM + */ +#define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT #endif /** @@ -261,7 +264,6 @@ void IRPinChangeInterruptHandler(void) { } } - else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) { /* * Start of data mark here, check data space length @@ -335,7 +337,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 @@ -348,17 +350,17 @@ 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 TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; #endif # if defined(LOCAL_DEBUG) - Serial.print(F("Parity check for command failed. Command=")); - Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); - Serial.print(F(" parity=")); - Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); + Serial.print(F("Parity check for command failed. Command=")); + Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); + Serial.print(F(" parity=")); + Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); # endif #else // No address, so command and parity are in the lowest bytes diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 65d87dcb2..f26478d6c 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,17 +71,20 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 // see: https://www.sbprojects.net/knowledge/ir/rc5.php // https://en.wikipedia.org/wiki/Manchester_code // https://en.wikipedia.org/wiki/RC-5 -// https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended // mark->space => 0 // space->mark => 1 -// MSB first 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command, no stop bit -// Field bit is 1 for RC5 and inverted 7. command bit for RC5X. That way the first 64 commands of RC5X remain compatible with the original RC5. +// MSB first, 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command, no stop bit +// Field bit is 1 for RC5 and 0 (=inverted 7. command bit) for RC5X. That way the first 64 commands of RC5X are indistinguishable from RC5. // SF TAAA AACC CCCC -// IR duty factor is 25%, +// IR duty factor is 25% +// +// MARANTZ +// https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended +// Marantz uses RC5X and adds a a pause after the address / first 8 bits +// After the 6 bit command another 6 bit command extension is sent // #define RC5_ADDRESS_BITS 5 #define RC5_COMMAND_BITS 6 -#define RC5_EXTENSION_BITS 6 #define RC5_COMMAND_FIELD_BIT 1 #define RC5_TOGGLE_BIT 1 @@ -91,22 +94,35 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 #define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7 - Divided by 2 to handle the bit sequence of 01010101 which gives one mark and space for each 2 bits -#define RC5_DURATION (15L * RC5_UNIT) // 13335 +#define RC5_DURATION (15 * RC5_UNIT) // 13335 #define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792 #define RC5_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - RC5_DURATION) // 100 ms #define RC5_MAXIMUM_REPEAT_DISTANCE (RC5_REPEAT_DISTANCE + (RC5_REPEAT_DISTANCE / 4)) // Just a guess +#define MARANTZ_COMMAND_EXTENSION_BITS 6 +#define MARANTZ_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS) // 19 +#define MARANTZ_PAUSE_BIT_INDEX (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS) // 7 +#define MARANTZ_PAUSE_DURATION (4 * RC5_UNIT) // 3556 + +#define MARANTZ_DURATION (24 * RC5_UNIT) // RC5 + 6 Extension bits + 4 pause units = 22225 +#define MARANTZ_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - MARANTZ_DURATION) // 100 ms + + /************************************ * Start of send and decode functions ************************************/ /** * !!! Not tested, because no Marantz remote was at hand and no receive function was contributed!!! - * @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X. - * @param aMarantzExtension 6 bit command extension which is sent after aCommand. aCommand and aMarantzExtension are sent after a short pause. + * Send function for the Marantz version of RC5(X) with a pause of 4 * RC5_UNIT after address / first 8 bits + * and before the bits of command and command extension. + * Marantz seems to require at least one repetition with toggle bit set + * @param aAddress 5 address bits to be sent first (MSB first). + * @param aCommand 6 or 7 (RC5X) bits. If aCommand is >=0x40 then we switch automatically to RC5X. + * @param aMarantzExtension 6 bit command extension which is sent after 6 command bits of aCommand. aCommand and aMarantzExtension are sent after a short pause. * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. */ -void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats, +void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats,uint8_t aMarantzExtension, bool aEnableAutomaticToggle) { // Set IR carrier frequency @@ -126,8 +142,8 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantz tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); // 1 << 6 = 0x40 } - // Set the command to the 2nd part of data to be sent after the pause - uint16_t tIRExtData = (aCommand << RC5_EXTENSION_BITS); + // Combine command and command extension for the 2nd part of data to be sent after the pause + uint16_t tIRExtData = (aCommand << MARANTZ_COMMAND_EXTENSION_BITS); // Set the Marantz command extension bits tIRExtData |= (aMarantzExtension & 0x3F); @@ -147,21 +163,22 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantz // start bit is sent by sendBiphaseData followed by the field bit and toggle bit and address sendBiphaseData(RC5_UNIT, tIRData, RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); // pause before the bits of command and command extension to indicate that it's Marantz-RC5x - space(4 * RC5_UNIT); // Marantz-RC5x has a pause before the bits of command and command extension + space(MARANTZ_PAUSE_DURATION); // Marantz-RC5x has a pause before the bits of command and command extension // send command and command extension - sendBiphaseData(RC5_UNIT, tIRExtData, RC5_COMMAND_BITS + RC5_EXTENSION_BITS, false); + sendBiphaseData(RC5_UNIT, tIRExtData, RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS, false); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { // send repeated command in a fixed raster - delay(RC5_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI); + delay(MARANTZ_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI); } } } /** - * @param aCommand If aCommand is >=0x40 then we switch automatically to RC5X. + * @param aAddress 5 address bits to be sent first (MSB first). + * @param aCommand 6 or 7 (RC5X) bits. If aCommand is >=0x40 then we switch automatically to RC5X. * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. */ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) { @@ -209,14 +226,87 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe } } +/* + * Static variables for the getBiphaselevel function + */ +uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array +uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. +uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. +uint16_t sBiphaseTimeUnit; + +void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) { + sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset; + sBiphaseTimeUnit = aBiphaseTimeUnit; + sBiphaseUsedTimingIntervals = 0; +} + +/** + * Gets the level of one time interval (aBiphaseTimeUnit) at a time from the raw buffer. + * The RC5/6 decoding is easier if the data is broken into time intervals. + * E.g. if the buffer has mark for 2 time intervals and space for 1, + * successive calls to getBiphaselevel will return 1, 1, 0. + * + * _ _ _ _ _ _ _ _ _ _ _ _ _ + * _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period + * _ _ _ ___ _ ___ ___ _ - Mark + * Data _____| |___| |_| |_| |_| |___| |___| |_| | - Data starts with a mark->space bit + * 1 0 0 0 1 1 0 1 0 1 1 - Space + * A mark to space at a significant clock edge results in a 1 + * A space to mark at a significant clock edge results in a 0 + * Returns current level [MARK or SPACE] or NO_MARK_OR_SPACE for error (measured time interval is not a multiple of sBiphaseTimeUnit). + */ +uint_fast8_t IRrecv::getBiphaselevel() { + uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK) + + if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawlen) { + return SPACE; // After end of recorded buffer, assume space. + } + + tLevelOfCurrentInterval = (sBiphaseDecodeRawbuffOffset) & 1; // on odd rawbuf offsets we have mark timings + + /* + * Setup data if sUsedTimingIntervals is 0 + */ + if (sBiphaseUsedTimingIntervals == 0) { + uint16_t tCurrentTimingWith = irparams.rawbuf[sBiphaseDecodeRawbuffOffset]; + uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS; + + if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) { + sBiphaseCurrentTimingIntervals = 1; + } else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { + sBiphaseCurrentTimingIntervals = 2; + } else if (matchTicks(tCurrentTimingWith, (3 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { + sBiphaseCurrentTimingIntervals = 3; + } else { + return NO_MARK_OR_SPACE; + } + } + +// We use another interval from tCurrentTimingIntervals + sBiphaseUsedTimingIntervals++; + +// keep track of current timing offset + if (sBiphaseUsedTimingIntervals >= sBiphaseCurrentTimingIntervals) { + // we have used all intervals of current timing, switch to next timing value + sBiphaseUsedTimingIntervals = 0; + sBiphaseDecodeRawbuffOffset++; + } + + IR_TRACE_PRINTLN(tLevelOfCurrentInterval); + + return tLevelOfCurrentInterval; +} + /** * Try to decode data as RC5 protocol * mark->space => 0 * space->mark => 1 * _ _ _ _ _ _ _ _ _ _ _ _ _ * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of each data bit period - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ sample point for bit value + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value * _ _ * 2 Start bits for RC5 _____| |_| ..|...|.. * @@ -251,6 +341,9 @@ bool IRrecv::decodeRC5() { /* * Get data bits - MSB first */ +#if defined(DECODE_MARANTZ) + bool RC5Marantz = false; +#endif for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) { // get next 2 levels and check for transition uint8_t tStartLevel = getBiphaselevel(); @@ -262,6 +355,28 @@ bool IRrecv::decodeRC5() { } else if ((tStartLevel == MARK) && (tEndLevel == SPACE)) { // we have a mark to space transition here tDecodedRawData = (tDecodedRawData << 1) | 0; +#if defined(DECODE_MARANTZ) + } else if (tBitIndex == MARANTZ_PAUSE_BIT_INDEX) { + Serial.print(F("Off=")); + Serial.print(sBiphaseDecodeRawbuffOffset); + Serial.print(F(" ticks=")); + Serial.print(irparams.rawbuf[sBiphaseDecodeRawbuffOffset]); + Serial.print(F(" + ")); + Serial.print(irparams.rawbuf[sBiphaseDecodeRawbuffOffset + 1]); + Serial.println(); + /* + * Check for RC5 Marantz format i.e. long space after 8 bits (including start bit) + * Check if timing buffer contains a pause, which is longer than 3/4 the expected pause + */ + if (irparams.rawbuf[sBiphaseDecodeRawbuffOffset] > (((MARANTZ_PAUSE_DURATION * 3)/ MICROS_PER_TICK * 4))) { + RC5Marantz = true; + // consume the long space + getBiphaselevel(); + getBiphaselevel(); + getBiphaselevel(); + getBiphaselevel(); + } +#endif } else { #if defined(LOCAL_DEBUG) Serial.print(F("RC5: ")); @@ -277,11 +392,26 @@ bool IRrecv::decodeRC5() { LongUnion tValue; tValue.ULong = tDecodedRawData; decodedIRData.decodedRawData = tDecodedRawData; + +#if defined(DECODE_MARANTZ) + if (RC5Marantz) { + decodedIRData.extra = tValue.UWord.LowWord & 0x3F; + decodedIRData.command = (tValue.UWord.LowWord > MARANTZ_COMMAND_EXTENSION_BITS) & 0x3F; + decodedIRData.address = (tValue.ULong >> (RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS)) & 0x1F; + + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; + if (tValue.ULong & (1L << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS))) { + decodedIRData.flags |= IRDATA_FLAGS_TOGGLE_BIT; + } + decodedIRData.protocol = MARANTZ; + } else { +#endif decodedIRData.command = tValue.UByte.LowByte & 0x3F; decodedIRData.address = (tValue.UWord.LowWord >> RC5_COMMAND_BITS) & 0x1F; - // Get the inverted 7. command bit for RC5X, the inverted value is always 1 for RC5 and serves as a second start bit. + // Get the inverted 7. command bit to decide if we have RC5X. For RC5, the inverted value is always 1 and serves as a second start bit. if ((tValue.UWord.LowWord & (1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS))) == 0) { + // Here we have detected RC5X! decodedIRData.command += 0x40; } @@ -291,6 +421,9 @@ bool IRrecv::decodeRC5() { } decodedIRData.protocol = RC5; +#if defined(DECODE_MARANTZ) + } +#endif // check for repeat checkForRepeatSpaceTicksAndSetFlag(RC5_MAXIMUM_REPEAT_DISTANCE / MICROS_PER_TICK); @@ -352,7 +485,7 @@ bool IRrecv::decodeRC5() { /** * Main RC6 send function */ -void IRsend::sendRC6(uint32_t aRawData, uint8_t aNumberOfBitsToSend) { +void IRsend::sendRC6(uint32_t aRawData, uint8_t aNumberOfBitsToSend) { // Deprecated sendRC6Raw(aRawData, aNumberOfBitsToSend); } void IRsend::sendRC6Raw(uint32_t aRawData, uint8_t aNumberOfBitsToSend) { @@ -386,7 +519,7 @@ void IRsend::sendRC6Raw(uint32_t aRawData, uint8_t aNumberOfBitsToSend) { * Send RC6 64 bit raw data * Can be used to send RC6A with ?31? data bits */ -void IRsend::sendRC6(uint64_t aRawData, uint8_t aNumberOfBitsToSend) { +void IRsend::sendRC6(uint64_t aRawData, uint8_t aNumberOfBitsToSend) { // Deprecated sendRC6Raw(aRawData, aNumberOfBitsToSend); } void IRsend::sendRC6Raw(uint64_t aRawData, uint8_t aNumberOfBitsToSend) { @@ -540,12 +673,13 @@ bool IRrecv::decodeRC6() { // Set Biphase decoding start values initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark + space -// Process first bit, which is known to be a 1 (mark->space) + // Check first bit, which is known to be a 1 (mark->space) if (getBiphaselevel() != MARK) { IR_DEBUG_PRINT(F("RC6: ")); IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK")); return false; } + // Check second bit if (getBiphaselevel() != SPACE) { IR_DEBUG_PRINT(F("RC6: ")); IR_DEBUG_PRINTLN(F("second getBiphaselevel() is not SPACE")); @@ -557,21 +691,21 @@ bool IRrecv::decodeRC6() { uint8_t tEndLevel; // end level of coded bit tStartLevel = getBiphaselevel(); + tEndLevel = getBiphaselevel(); + if (tBitIndex == RC6_TOGGLE_BIT_INDEX) { - // Toggle bit is double wide; make sure second half is equal first half - if (tStartLevel != getBiphaselevel()) { + /* + * Toggle bit is double wide; level of 1. and 2. time slot and 3. and 4.time slot must be equal + */ + if (tStartLevel != tEndLevel) { // 1. and 2. time slot must be equal #if defined(LOCAL_DEBUG) Serial.print(F("RC6: ")); Serial.println(F("Toggle mark or space length is wrong")); #endif return false; } - } - - tEndLevel = getBiphaselevel(); - if (tBitIndex == RC6_TOGGLE_BIT_INDEX) { - // Toggle bit is double wide; make sure second half matches - if (tEndLevel != getBiphaselevel()) { + tEndLevel = getBiphaselevel(); + if (tEndLevel != getBiphaselevel()) { // 3. and 4. time slot must be equal #if defined(LOCAL_DEBUG) Serial.print(F("RC6: ")); Serial.println(F("Toggle mark or space length is wrong")); @@ -667,7 +801,7 @@ void IRsend::sendRC5(uint32_t data, uint8_t nbits) { } /* - * Not longer required, use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead + * Deprecated, use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead */ void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) { // Set IR carrier frequency diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 52162cd95..b549ffe11 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -2265,10 +2265,52 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { } # endif // defined(SEND_PWM_BY_TIMER) +#elif defined(VEGA_ARIES_V2) || defined(VEGA_ARIES_V3) || defined(VEGA_ARIES_IOT) || defined(VEGA_ARIES_MICRO) +#include "Timer.h" +Timer Timer(0); + +#define TIMER_RESET_INTR_PENDING +#define TIMER_ENABLE_RECEIVE_INTR Timer.attachInterrupt(IRTimerInterruptHandler) +#define TIMER_DISABLE_RECEIVE_INTR Timer.detachInterrupt() + +void timerEnableReceiveInterrupt() { + Timer.resume(); +} +void timerDisableReceiveInterrupt() { + Timer.stop(); +} + +# if defined(ISR) +#undef ISR +# endif +#define ISR() void IRTimerInterruptHandler(void) +void IRTimerInterruptHandler(void); + +void timerConfigForReceive() { + Timer.initialize(MICROS_PER_TICK); // 50 uS + Timer.attachInterrupt(IRTimerInterruptHandler); + Timer.resume(); +} + +# if defined(SEND_PWM_BY_TIMER) +#define ENABLE_SEND_PWM_BY_TIMER +#define DISABLE_SEND_PWM_BY_TIMER + +void timerConfigForSend(uint8_t aFrequencyKHz) { + TIMER_DISABLE_RECEIVE_INTR; +# if defined(IR_SEND_PIN) + pinMode(IR_SEND_PIN, OUTPUT); +# else + pinMode(IrSender.sendPin, OUTPUT); +# endif + (void) aFrequencyKHz; +} +# endif // defined(SEND_PWM_BY_TIMER) + +#else // CPU types /*************************************** * Unknown CPU board ***************************************/ -#else #error Internal code configuration error, no timer functions implemented for this CPU / board /* * Dummy definitions to avoid more irritating compile errors From ba70bda3c238d88fc890c89bd083051ad204e1c6 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 20 Feb 2026 19:43:53 +0100 Subject: [PATCH 117/133] Added Marantz protocol, improved biphase decoding --- .github/workflows/LibraryBuild.yml | 6 +- README.md | 10 +- changelog.md | 2 + .../IRDispatcherDemo/DemoIRCommandMapping.h | 39 +- .../IRDispatcherDemo/IRDispatcherDemo.ino | 148 +- .../ReceiveAndSendDistanceWidth.ino | 5 + examples/ReceiveDemo/ReceiveDemo.ino | 4 + .../ReceiverTimingAnalysis.ino | 2 +- examples/UnitTest/UnitTest.ino | 103 +- examples/UnitTest/UnitTest.log | 2289 +++++++++-------- src/IRCommandDispatcher.h | 69 +- src/IRCommandDispatcher.hpp | 323 ++- src/IRProtocol.h | 4 +- src/IRProtocol.hpp | 22 +- src/IRReceive.hpp | 392 ++- src/IRSend.hpp | 138 +- src/IRremote.hpp | 7 +- src/IRremoteInt.h | 56 +- src/LocalDebugLevelEnd.h | 45 + src/LocalDebugLevelStart.h | 94 + src/TinyIRReceiver.hpp | 60 +- src/TinyIRSender.hpp | 10 +- src/ac_LG.hpp | 61 +- src/ir_BangOlufsen.hpp | 150 +- src/ir_BoseWave.hpp | 30 +- src/ir_Denon.hpp | 58 +- src/ir_DistanceWidthProtocol.hpp | 49 +- src/ir_FAST.hpp | 36 +- src/ir_JVC.hpp | 28 +- src/ir_Kaseikyo.hpp | 54 +- src/ir_LG.hpp | 59 +- src/ir_Lego.hpp | 57 +- src/ir_MagiQuest.hpp | 67 +- src/ir_NEC.hpp | 42 +- src/ir_OpenLASIR.hpp | 31 +- src/ir_Pronto.hpp | 25 +- src/ir_RC5_RC6.hpp | 313 ++- src/ir_Samsung.hpp | 18 +- src/ir_Sony.hpp | 27 +- src/ir_Template.hpp | 8 +- 40 files changed, 2551 insertions(+), 2390 deletions(-) create mode 100644 src/LocalDebugLevelEnd.h create mode 100644 src/LocalDebugLevelStart.h diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index e7f4b6349..84ce6eb73 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -1,7 +1,7 @@ # https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/.github/workflows/LibraryBuild.yml # Github workflow script to test compile all examples of an Arduino library repository. # -# Copyright (C) 2020-2023 Armin Joachimsmeyer +# Copyright (C) 2020-2026 Armin Joachimsmeyer # https://github.com/ArminJo/Github-Actions # # Before being able to push to my .github\workflows directories, @@ -321,9 +321,9 @@ jobs: - arduino-boards-fqbn: vega:riscv:aries_v3 platform-url: https://gitlab.com/riscv-vega/vega-arduino/-/raw/main/package_vega_index.json - #sketches-exclude: AllProtocolsOnLCD,UnitTest,ReceiveAndSendDistanceWidth,ReceiveDemo,SimpleReceiverForHashCodes # No print(uint64_t,.) available + sketches-exclude: MicroGirs,SendLGAirConditionerDemo # No Stream:: available and readBytesUntil build-properties: # the flags were put in compiler.cpp.extra_flags - All: -DF_CPU=100000000LL -DVEGA_ARIES_V3 -DRAW_BUFFER_LENGTH=750 + All: -DF_CPU=100000000LL -DVEGA_ARIES_V3 -DRAW_BUFFER_LENGTH=750 -DCHANGE=1 # fail-fast: false # false -> do not cancel all jobs / architectures if one job fails diff --git a/README.md b/README.md index c85a2deb4..6acc62bef 100644 --- a/README.md +++ b/README.md @@ -678,10 +678,11 @@ static const char stop[] PROGMEM ="stop"; /* * Main mapping array of commands to C functions and command strings + * The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled */ const struct IRToCommandMappingStruct IRMapping[] = { -{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, blink20times }, -{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop }, +{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, +{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, /* * Short commands that can always be executed */ @@ -1021,7 +1022,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `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` | 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. | +| `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. Is set to 20 if `DO_NOT_USE_THRESHOLD_DECODER` is enabled. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE` | 50 if RAM <= 2k, else 200 | A value of 200 allows to decode mark or space durations up to 10 ms. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | @@ -1064,9 +1065,10 @@ These macros must be defined in your program before the line `#include diff --git a/changelog.md b/changelog.md index 67b4a8e2e..c6cdc461d 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,8 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Improved `decodeSamsung()`. - `OpenLASIR` protocol added by [danielweidman](https://github.com/danielweidman). - Added `DECODE_MARANTZ` and swapped parameter aMarantzExtension and aNumberOfRepeats of `sendMaranz()` to be consistent with other extensions. +- Improved biphase decoding. +- Improved debug output handling. - Moved `IRCommandDispatcher` from demo to main library folder. # 4.5.0 - does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt. diff --git a/examples/IRDispatcherDemo/DemoIRCommandMapping.h b/examples/IRDispatcherDemo/DemoIRCommandMapping.h index 929eafdf7..4e473b007 100644 --- a/examples/IRDispatcherDemo/DemoIRCommandMapping.h +++ b/examples/IRDispatcherDemo/DemoIRCommandMapping.h @@ -47,11 +47,7 @@ #if defined(USE_KEYES_REMOTE_CLONE) #define IR_REMOTE_NAME "KEYES_CLONE" // Codes for the KEYES CLONE remote control with 17 keys with number pad above direction control -#if defined(USE_IRMP_LIBRARY) -#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit -#else #define IR_ADDRESS 0x00 -#endif #define IR_UP 0x18 #define IR_DOWN 0x52 @@ -105,11 +101,7 @@ * IR code to button mapping for better reading. IR codes should only referenced here. */ // Codes for the KEYES remote control with 17 keys and direction control above number pad -#if defined(USE_IRMP_LIBRARY) -#define IR_ADDRESS 0xFF00 // IRMP interprets NEC addresses always as 16 bit -#else #define IR_ADDRESS 0x00 -#endif #define IR_UP 0x46 #define IR_DOWN 0x15 @@ -178,32 +170,33 @@ static const char printMenu[] PROGMEM ="printMenu"; static const char reset[] PROGMEM ="reset"; static const char stop[] PROGMEM ="stop"; -// not used yet -static const char test[] PROGMEM ="test"; -static const char pattern[] PROGMEM ="pattern"; - /* * Main mapping array of commands to C functions and command strings + * The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled */ const struct IRToCommandMappingStruct IRMapping[] = { /**/ -{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, blink20times }, /**/ -{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, stop }, +{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, /**/ +{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, /* */ + +/* + * Short commands that can always be executed, but must be able to terminate other blocking commands (only doLedBlink20times() in this example) + */ +{ COMMAND_START, IR_COMMAND_FLAG_BLOCKING, &doLedBlinkStart, COMMAND_STRING(blinkStart) }, /**/ +{ COMMAND_ON, IR_COMMAND_FLAG_BLOCKING, &doLedOn, COMMAND_STRING(LEDon) }, /**/ +{ COMMAND_OFF, IR_COMMAND_FLAG_BLOCKING, &doLedOff, COMMAND_STRING(LEDoff) }, /**/ /* * Short commands that can always be executed */ -{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 }, /**/ -{ COMMAND_TONE3, IR_COMMAND_FLAG_NON_BLOCKING, &doPrintMenu, printMenu }, /**/ -{ COMMAND_ON, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOn, LEDon }, /**/ -{ COMMAND_OFF, IR_COMMAND_FLAG_NON_BLOCKING, &doLedOff, LEDoff }, /**/ -{ COMMAND_START, IR_COMMAND_FLAG_NON_BLOCKING, &doLedBlinkStart, blinkStart }, /**/ -{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, reset }, +{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, COMMAND_STRING(tone1800) }, /* Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled */ +{ COMMAND_TONE3, IR_COMMAND_FLAG_NON_BLOCKING, &doPrintMenu, COMMAND_STRING(printMenu) }, /**/ +{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, COMMAND_STRING(reset) }, /* * Repeatable short commands */ -{ COMMAND_TONE2, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doTone2200, tone2200 }, /**/ -{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, /**/ -{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, decreaseBlink } }; +{ COMMAND_TONE2, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doTone2200, COMMAND_STRING(tone2200) }, /* Lasts 50 ms and allows receiving of repeats */ +{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, COMMAND_STRING(increaseBlink) }, /**/ +{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, COMMAND_STRING(decreaseBlink) } }; #endif // _IR_COMMAND_MAPPING_H diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index cf4228254..b9a0194ee 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -32,10 +32,17 @@ //#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding //#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding //#define USE_IRMP_LIBRARY // The IRMP library is used for decoding -//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt. +//#define DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT // Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry. +#define NO_LED_FEEDBACK_CODE // We use LED_BUILTIN for command feedback and therefore cannot use is as IR receiving feedback +#define INFO // To see some informative output of the IRCommandDispatcher library +//#define DEBUG // To see some additional debug output of the IRCommandDispatcher library + #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -#if defined(USE_TINY_IR_RECEIVER) && defined(TONE_PIN) +#if defined(INFO) || defined(DEBUG) +#define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries. +#endif +#if defined(TONE_PIN) #define DISPATCHER_BUZZER_FEEDBACK_PIN TONE_PIN // The pin to be used for the optional 50 ms buzzer feedback before executing a command. Only available for TinyIR. #endif @@ -44,8 +51,6 @@ #define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol //#define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 //#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory - -void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration); #endif // defined(USE_IRMP_LIBRARY) bool doBlink = false; @@ -70,11 +75,13 @@ void doTone2200(); /* * Set definitions and include IRCommandDispatcher library after the declaration of all commands required for mapping */ -#define INFO // to see some informative output of the IRCommandDispatcher library #include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IRMapping array, IR_ADDRESS etc. -#include "IRCommandDispatcher.hpp" +#include "IRCommandDispatcher.hpp" // This can optionally set USE_TINY_IR_RECEIVER + +void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration); -void setup() { +void setup() +{ pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); @@ -105,23 +112,33 @@ void setup() { IRDispatcher.printIRInfo(&Serial); doPrintMenu(); +#if defined(DEBUG) && defined(SP) + Serial.print(F("SP=0x")); + Serial.println(SP, HEX); +#endif } -void loop() { +void loop() +{ IRDispatcher.checkAndRunSuspendedBlockingCommands(); - if (doBlink) { + if (doBlink) + { digitalWrite(LED_BUILTIN, HIGH); DELAY_AND_RETURN_IF_STOP(sBlinkDelay); digitalWrite(LED_BUILTIN, LOW); DELAY_AND_RETURN_IF_STOP(sBlinkDelay); } - if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000) { - //Short beep as remainder, if we did not receive any command in the last 2 minutes - IRDispatcher.IRReceivedData.MillisOfLastCode += 120000; + if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000) + { + // Short beep as remainder, if we did not receive any command in the last 2 minutes + IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); doTone1800(); +#if defined(INFO) + Serial.println(F("2 minutes timeout")); +#endif } // delay(10); @@ -130,7 +147,8 @@ void loop() { /* * Menu for simple China Keyes or Keyes clone IR controls with number pad and direction control pad */ -void doPrintMenu() { +void doPrintMenu() +{ Serial.println(); Serial.println(F("Press 1 for tone 1800 Hz")); Serial.println(F("Press 2 for tone 2200 Hz")); @@ -148,39 +166,50 @@ void doPrintMenu() { /* * Here the actions that are matched to IR keys */ -void doLedOn() { +void doLedOn() +{ digitalWrite(LED_BUILTIN, HIGH); doBlink = false; } -void doLedOff() { +void doLedOff() +{ digitalWrite(LED_BUILTIN, LOW); doBlink = false; } -void doIncreaseBlinkFrequency() { +void doIncreaseBlinkFrequency() +{ doBlink = true; - if (sBlinkDelay > 5) { + if (sBlinkDelay > 5) + { sBlinkDelay -= sBlinkDelay / 4; } } -void doDecreaseBlinkFrequency() { +void doDecreaseBlinkFrequency() +{ doBlink = true; sBlinkDelay += sBlinkDelay / 4; } -void doStop() { +void doStop() +{ doBlink = false; + digitalWrite(LED_BUILTIN, LOW); } -void doResetBlinkFrequency() { +void doResetBlinkFrequency() +{ sBlinkDelay = 200; digitalWrite(LED_BUILTIN, LOW); } -void doLedBlinkStart() { +void doLedBlinkStart() +{ doBlink = true; } /* * This is a blocking function which checks for stop */ -void doLedBlink20times() { - for (int i = 0; i < 20; ++i) { +void doLedBlink20times() +{ + for (int i = 0; i < 20; ++i) + { digitalWrite(LED_BUILTIN, HIGH); DELAY_AND_RETURN_IF_STOP(200); digitalWrite(LED_BUILTIN, LOW); @@ -188,46 +217,63 @@ void doLedBlink20times() { } } -void doTone1800() { -#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) && defined(TONE_PIN) - irmp_tone(TONE_PIN, 1800, 200); -#elif !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone() stops timer 1 for ESP8266 - tone(TONE_PIN, 1800, 200); +/* + * Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled + */ +void doTone1800() +{ +#if defined(TONE_PIN) + IRremoteTone(TONE_PIN, 1800, 200); #endif } -void doTone2200() { -#if defined(USE_IRMP_LIBRARY) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) && defined(TONE_PIN) - // use IRMP compatible function for tone() - irmp_tone(TONE_PIN, 2200, 50); -#elif !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN) // tone() stops timer 1 for ESP8266 - tone(TONE_PIN, 2200, 50); +/* + * Lasts 50 ms and allows receiving of repeats + */ +void doTone2200() +{ +#if defined(TONE_PIN) + IRremoteTone(TONE_PIN, 2200, 50); #endif } -#if defined(USE_IRMP_LIBRARY) /* - * Convenience IRMP compatible wrapper function for Arduino tone() if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is NOT activated + * Convenience IR library wrapper function for Arduino tone() * It currently disables the receiving of repeats * It is not part of the library because it statically allocates the tone interrupt vector 7. */ -void irmp_tone(uint8_t _pin, unsigned int frequency, unsigned long duration) { -# if defined(__AVR__) && !defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) +void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration) +{ + // IRMP_ENABLE_PIN_CHANGE_INTERRUPT currently disables the receiving of repeats +#if defined(ESP8266) || defined(NRF5) || defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive(). + (void) aTonePin; + (void) aFrequency; + (void) aDuration; + return; +#else + /* + * Stop receiver, generate a single beep and start receiver again + */ +# if defined(ESP32) || defined(USE_TINY_IR_RECEIVER )// ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too. + tone(aTonePin, aFrequency, aDuration); +# else +# if defined(USE_IRREMOTE_LIBRARY) + IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource. +# else storeIRTimer(); - tone(_pin, frequency, 0); - if (duration == 0) { - duration = 100; +# endif + tone(aTonePin, aFrequency, 0); + if (aDuration == 0) + { + aDuration = 100; } - delay(duration); - noTone(_pin); + delay(aDuration); + noTone(aTonePin); +# if defined(USE_IRREMOTE_LIBRARY) + IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked. +# else restoreIRTimer(); -#elif defined(ESP8266) - // tone() stops timer 1 - (void) _pin; - (void) frequency; - (void) duration; -#else - tone(_pin, frequency, duration); +# endif +# endif #endif } -#endif // #if defined(USE_IRMP_LIBRARY) diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index dac652bb4..cece3cc79 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -182,7 +182,12 @@ void loop() { if (sDecodedRawDataArray[0] != IrReceiver.decodedIRData.decodedRawDataArray[0]) { *sDecodedRawDataArray = *IrReceiver.decodedIRData.decodedRawDataArray; // copy content here Serial.print(F("Store new sDecodedRawDataArray[0]=0x")); +# if (__INT_WIDTH__ < 32) Serial.println(IrReceiver.decodedIRData.decodedRawDataArray[0], HEX); +# else + PrintULL::print(&Serial, IrReceiver.decodedIRData.decodedRawDataArray[0], HEX); +# endif + } } IrReceiver.resume(); // resume receiver diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 43d228708..4929717b7 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -245,7 +245,11 @@ void loop() { if (IrReceiver.decodedIRData.protocol == UNKNOWN) { auto tDecodedRawData = IrReceiver.decodedIRData.decodedRawData; // uint32_t on 8 and 16 bit CPUs and uint64_t on 32 and 64 bit CPUs Serial.print(F("Raw data from hash decoder is 0x")); +# if (__INT_WIDTH__ < 32) Serial.println(tDecodedRawData); +# else + PrintULL::println(&Serial, tDecodedRawData, BIN); +# endif } else { /* diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index 8f9fb53d5..6ed6ba1c6 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -76,7 +76,7 @@ void setup() { # 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); + attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE); // CHANGE can also be an enum :-( # endif #endif Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN))); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 5a50d6821..a2b587dee 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -62,7 +62,7 @@ // 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 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,6 +79,7 @@ #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604 #define DECODE_JVC #define DECODE_RC5 +#define DECODE_MARANTZ #define DECODE_RC6 #define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols @@ -97,7 +98,7 @@ #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). +#define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz instead of 455 kHz in order to be able to test it #endif #define DECODE_BOSEWAVE @@ -362,7 +363,19 @@ void ReceiveCompleteCallbackHandler() { sDataJustReceived = true; } -void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { +/* + * Must be called after checkReceive, because it does not wait for signal to be received and does not call decode() + */ +void checkReceivedExtra(uint16_t aSentExtra) { + if (IrReceiver.decodedIRData.extra != aSentExtra) { + Serial.print(F("ERROR: Received extra=0x")); + Serial.print(IrReceiver.decodedIRData.extra, HEX); + Serial.print(F(" != sent extra=0x")); + Serial.println(aSentExtra, HEX); + } +} + +void waitForReceived() { // wait until signal has received uint16_t tTimeoutCounter = 1000; // gives 10 seconds timeout while (!sDataJustReceived) { @@ -374,6 +387,15 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { tTimeoutCounter--; } sDataJustReceived = false; +} + +/* + * @return true if NO error, false if error + */ +bool checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { + bool tReturnValueIsSuccess = true; + + waitForReceived(); if (IrReceiver.decode()) { // Print a short summary of received data @@ -403,6 +425,7 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { if (IrReceiver.decodedIRData.protocol == UNKNOWN) { Serial.println(F("ERROR: Unknown protocol")); + tReturnValueIsSuccess = false; } else { /* * Check address @@ -412,6 +435,7 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { Serial.print(IrReceiver.decodedIRData.address, HEX); Serial.print(F(" != sent address=0x")); Serial.println(aSentAddress, HEX); + tReturnValueIsSuccess = false; } /* * Check command @@ -421,14 +445,17 @@ void checkReceive(uint16_t aSentAddress, uint16_t aSentCommand) { Serial.print(IrReceiver.decodedIRData.command, HEX); Serial.print(F(" != sent command=0x")); Serial.println(aSentCommand, HEX); + tReturnValueIsSuccess = false; } } } else { Serial.println(F("No data received")); + tReturnValueIsSuccess = false; IrReceiver.resume(); } Serial.println(); + return tReturnValueIsSuccess; } /* @@ -518,7 +545,9 @@ void loop() { 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); + waitForReceived(); + IrReceiver.printIRResultRawFormatted(&Serial, true); + IrReceiver.resume(); delay(DELAY_AFTER_SEND); # if defined(DECODE_NEC) @@ -791,10 +820,12 @@ void loop() { checkReceive(sAddress & 0xFFF, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Kaseikyo with 0x4711 as Vendor ID")); + Serial.println(F("Send Kaseikyo with extra=0x4711 as Vendor ID")); Serial.flush(); IrSender.sendKaseikyo(sAddress & 0xFFF, sCommand, sRepeats, 0x4711); - checkReceive(sAddress & 0xFFF, sCommand); + if (checkReceive(sAddress & 0xFFF, sCommand)) { + checkReceivedExtra(0x4711); + } delay(DELAY_AFTER_SEND); Serial.println(F("Send Kaseikyo_Denon variant")); @@ -805,13 +836,13 @@ void loop() { #endif #if defined(DECODE_DENON) - Serial.println(F("Send Denon with repeats")); + Serial.println(F("Send Denon with 2 autorepeats after 45 ms")); // Only first frame is received! Serial.flush(); IrSender.sendDenon(sAddress & 0x1F, sCommand, sRepeats); checkReceive(sAddress & 0x1F, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Denon/Sharp variant with repeats")); + Serial.println(F("Send Denon/Sharp variant with 2 autorepeat5 after 45 ms")); Serial.flush(); IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats); checkReceive(sAddress & 0x1F, sCommand); @@ -831,9 +862,16 @@ void loop() { checkReceive(sAddress & 0xFF, sCommand & 0x7F); delay(DELAY_AFTER_SEND); +# if defined(DECODE_BEO) + // BEO sets RECORD_GAP_MICROS 16000 which leads to concatenating the Sony repeats + Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits and no repeats")); + Serial.flush(); + IrSender.sendSony(sAddress & 0x1FFF, sCommand, 0, SIRCS_20_PROTOCOL); +# else Serial.println(F("Send Sony/SIRCS with 7 command and 13 address bits")); Serial.flush(); IrSender.sendSony(sAddress & 0x1FFF, sCommand, sRepeats, SIRCS_20_PROTOCOL); +# endif checkReceive(sAddress & 0x1FFF, sCommand & 0x7F); delay(DELAY_AFTER_SEND); #endif @@ -878,6 +916,26 @@ void loop() { delay(DELAY_AFTER_SEND); #endif +#if defined(DECODE_MARANTZ) + Serial.print(F("Send Marantz with RC5 and extra=0x")); + Serial.println(~sCommand & 0x3F, HEX); + Serial.flush(); + IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sRepeats, ~sCommand & 0x3F, true); // 5 address, 6 command bits + if (checkReceive(sAddress & 0x1F, sCommand & 0x3F)) { + checkReceivedExtra(~sCommand & 0x3F); + } + delay(DELAY_AFTER_SEND); + + Serial.print(F("Send Marantz with RC5A and extra=0x")); + Serial.println(~sCommand & 0x3F, HEX); + Serial.flush(); + IrSender.sendRC5Marantz(sAddress & 0x1F, (sCommand & 0x3F) + 0x40, sRepeats, ~sCommand & 0x3F, true); // 5 address, 7 command bits + if (checkReceive(sAddress & 0x1F, (sCommand & 0x3F) + 0x40)) { + checkReceivedExtra(~sCommand & 0x3F); + } + delay(DELAY_AFTER_SEND); +#endif + #if defined(DECODE_RC6) Serial.println(F("Send RC6")); Serial.flush(); @@ -887,10 +945,12 @@ void loop() { checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send RC6A with 14 bit 0x2711 as extra")); + Serial.println(F("Send RC6A with 14 bit and extra=0x2711")); Serial.flush(); IrSender.sendRC6A(sAddress & 0xFF, sCommand, sRepeats, 0x2711, true); - checkReceive(sAddress & 0xFF, sCommand); + if (checkReceive(sAddress & 0xFF, sCommand)) { + checkReceivedExtra(0x2711); + } delay(DELAY_AFTER_SEND); #endif @@ -900,19 +960,21 @@ void loop() { Serial.println(tWandId, HEX); Serial.flush(); IrSender.sendMagiQuest(tWandId, s16BitCommand); // we have 31 bit address - checkReceive(sAddress, s16BitCommand & 0x1FF); // we have 9 bit command + if (checkReceive(sAddress, s16BitCommand & 0x1FF)) { // we have 9 bit command + checkReceivedExtra(0x6BCD); + } delay(DELAY_AFTER_SEND); #endif #if defined(DECODE_OPENLASIR) - Serial.println(F("Send OpenLASIR mode fire and color orange")); + Serial.println(F("Send OpenLASIR mode fire and color orange, detected as ONKYO")); Serial.flush(); IrSender.sendOpenLASIR(sAddress & 0xFF, sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE, sRepeats); - checkReceive(sAddress & 0xFF, IrSender.computeOpenLASIRRawCommand(sCommand, OPENLASIR_MODE_LASER_TAG_FIRE,OPENLASIR_COLOR_ORANGE)); + checkReceive(sAddress & 0xFF, + IrSender.computeOpenLASIRRawCommand(sCommand, OPENLASIR_MODE_LASER_TAG_FIRE, OPENLASIR_COLOR_ORANGE)); delay(DELAY_AFTER_SEND); #endif - #if defined(DECODE_LEGO_PF) Serial.println(F("Send Lego with 2 channel and with 4 command bits")); Serial.flush(); @@ -922,9 +984,9 @@ void loop() { #endif #if defined(DECODE_BEO) - Serial.println(F("Send Bang&Olufsen / originally with 455 kHz")); + Serial.println(F("Send 16 bit Bang&Olufsen / originally with 455 kHz")); Serial.flush(); - IrSender.sendBangOlufsen(sAddress & 0x0FF, sCommand, sRepeats); + IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats); // send 8 bit command and 8 bit address / header # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) delay((RECORD_GAP_MICROS / 1000) + 1); Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); @@ -951,7 +1013,7 @@ void loop() { } IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0]; # endif - checkReceive(sAddress & 0x0FF, sCommand); + checkReceive(sAddress & 0xFF, sCommand); // only 8 bit of address is sent delay(DELAY_AFTER_SEND); #endif @@ -1021,7 +1083,9 @@ void loop() { IrSender.mark(210); // 8 pulses at 38 kHz IrSender.space(540); // to fill up to 750 us } - checkReceive(sAddress, sCommand); + waitForReceived(); + IrReceiver.printIRResultRawFormatted(&Serial, true); + IrReceiver.resume(); delay(DELAY_AFTER_SEND); /* @@ -1037,6 +1101,9 @@ void loop() { sRepeats = 4; } + Serial.println(F("Invert toggle value for next loop")); + sLastSendToggleValue = !sLastSendToggleValue; + /* * Test stop and start of 50 us receiver timer */ diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 50ae4c4f5..f5246ce9e 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -1,177 +1,170 @@ -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 +START ../src/UnitTest.cpp from Feb 20 2026 +Using library version 4.6.0 +Ready to receive IR signals of protocols: NEC/NEC2/Onkyo/Apple, Panasonic/Kaseikyo, Denon/Sharp, Sony, RC5, RC6, LG, JVC, Samsung, Bang & Olufsen, FAST, Lego Power Functions, Bosewave, MagiQuest, OpenLASIR, Universal Pulse Distance Width, Hash at pin 2 Use ReceiveCompleteCallback Receive buffer length is 400 Send IR signals at pin 3 If you connect debug pin 5 to ground, raw data is always printed Send signal mark duration for 38kHz is 8 us, pulse narrowing correction is 3000 ns, total period is 26 us 16000 us is the (minimum) gap, after which the start of a new IR packet is assumed -20 us are subtracted from all marks and added to all spaces for decoding +40 us are subtracted from all marks and added to all spaces for decoding address=0xFFF1 command=0x76 Send NEC with 8 bit address -Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=754000us, Duration=67900us +Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=754900us, Duration=68000us Send with: IrSender.sendNEC(0xF1, 0x76, ); 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 -Duration=67900us + -754900 + +8900,-4450 + + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500 + + 600,-1650 + 600,-1600 + 600,-1650 + 600,-1650 + + 600,- 550 + 600,-1650 + 650,-1600 + 600,-1600 + + 600,- 550 + 600,- 550 + 600,- 500 + 650,- 500 + + 600,- 550 + 650,-1600 + 600,-1600 + 650,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 + + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 600,- 550 + 600,-1650 + + 650 +Duration=68000us Send NEC with 16 bit address -Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764850us, Duration=73400us +Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=764800us, Duration=73450us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); 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 + -764800 + +8900,-4450 + + 600,-1600 + 600,- 550 + 600,- 550 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1550 + + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,- 450 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,- 550 + + 600,-1650 + 600,- 500 + 600,- 550 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,- 500 + 650,-1600 + + 600 +Duration=73450us Send NEC2 with 16 bit address -Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=765200us, Duration=73450us +Protocol=NEC Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=765250us, Duration=73450us Send with: IrSender.sendNEC(0xFFF1, 0x76, ); rawIRTimings[68]: - -765200 - +8950,-4400 - + 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 + -765250 + +8900,-4450 + + 600,-1650 + 650,- 450 + 650,- 500 + 650,- 450 + + 650,-1600 + 600,-1650 + 650,-1600 + 650,-1550 + + 650,-1600 + 600,-1650 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,-1600 + 600,-1650 + 650,- 450 + + 650,-1600 + 650,-1600 + 600,-1650 + 650,- 450 + + 650,-1600 + 650,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + 650 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 + +8950,-4400 + + 600,- 950 +1050,- 450 + 550,-1950 +2050,- 450 + + 600,-2900 +3000,- 450 + 600,- 100 + 400 +Duration=29450us Send NEC data with 8 bit address 0x80 and command 0x45 and no repeats with sendPronto() -Protocol=NEC Address=0x80, Command=0x45, Raw-Data=0xBA457F80, 32 bits, LSB first, Gap=756450us, Duration=68550us +Protocol=NEC Address=0x80, Command=0x45, Raw-Data=0xBA457F80, 32 bits, LSB first, Gap=713750us, Duration=68500us Send with: IrSender.sendNEC(0x80, 0x45, ); rawIRTimings[68]: - -756450 + -713750 +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,- 500 + 650,- 500 + 650,- 550 + 600,- 550 + + 650,- 550 + 700,- 450 + 650,- 500 + 650,-1600 + + 650,-1600 + 650,-1550 + 700,-1550 + 650,-1550 + + 700,-1500 + 700,-1550 + 700,-1550 + 650,- 500 + + 700,-1500 + 700,- 500 + 650,-1600 + 650,- 500 + + 650,- 500 + 700,- 450 + 650,-1600 + 650,- 550 + + 700,- 450 + 750,-1450 + 700,- 450 + 700,-1550 + + 650,-1600 + 700,-1550 + 650,- 500 + 700,-1500 + 700 -Duration=68550us +Duration=68500us 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 +Protocol=NEC Address=0x4, Command=0x8, Raw-Data=0xF708FB04, 32 bits, LSB first, Gap=772450us, Duration=68100us Send with: IrSender.sendNEC(0x4, 0x8, ); rawIRTimings[68]: - -772400 + -772450 +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,- 450 + 600,- 550 + 650,-1600 + 600,- 500 + + 650,- 500 + 600,- 550 + 650,- 450 + 600,- 550 + + 650,-1600 + 650,-1600 + 600,- 500 + 600,-1650 + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 600,-1650 + + 600,- 550 + 650,- 500 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 650,-1650 + 600 Duration=68100us Send ONKYO with 16 bit address 0x0102 and 16 bit command 0x0304 with NECRaw(0x03040102) -Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=769500us, Duration=55700us +Protocol=Onkyo Address=0x102, Command=0x304, Raw-Data=0x3040102, 32 bits, LSB first, Gap=749650us, Duration=55650us 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 + -749650 + +8950,-4400 + + 650,- 500 + 600,-1650 + 600,- 500 + 600,- 550 + + 650,- 450 + 650,- 500 + 650,- 450 + 650,- 500 + + 600,-1650 + 600,- 500 + 650,- 500 + 650,- 450 + + 650,- 500 + 600,- 500 + 600,- 550 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1600 + 650,- 500 + 600,- 550 + + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500 + 650 -Duration=55700us +Duration=55650us Send ONKYO with 16 bit address 0x0102 and command 0x34 with old 32 bit format MSB first (0x40802CD3) -Protocol=NEC Address=0x102, Command=0x34, Raw-Data=0xCB340102, 32 bits, LSB first, Gap=771400us, Duration=61250us +Protocol=NEC Address=0x102, Command=0x34, Raw-Data=0xCB340102, 32 bits, LSB first, Gap=771400us, Duration=61300us 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 + + 600,- 550 + 600,-1600 + 650,- 500 + 650,- 500 + + 650,- 450 + 600,- 550 + 600,- 550 + 650,- 450 + + 600,-1650 + 650,- 500 + 600,- 500 + 600,- 550 + + 600,- 500 + 600,- 550 + 650,- 500 + 650,- 450 + + 600,- 550 + 600,- 500 + 700,-1550 + 650,- 500 + + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 550 + + 600,-1600 + 600,-1650 + 600,- 550 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,-1650 + 600,-1650 + 650 -Duration=61250us +Duration=61300us 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 +Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=770800us, Duration=55050us Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawIRTimings[100]: - -770850 - +3450,-1700 - + 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 + -770800 + +3550,-1650 + + 450,- 450 + 500,-1200 + 500,- 400 + 500,- 400 + + 500,- 400 + 500,- 400 + 500,- 350 + 450,- 450 + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 400 - + 500,- 350 + 500,-1250 + 550,- 350 + 500,-1250 + + 500,- 400 + 500,-1200 + 450,- 450 + 500,- 400 + + 500,- 350 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,-1250 + 450,-1300 + 450,- 450 + 400,-1300 + + 450,- 450 + 500,- 400 + 500,- 400 + 400,- 450 + + 500,- 400 + 450,- 450 + 500,- 350 + 500,- 450 + + 450,- 400 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,- 400 + 450,- 400 + 550,- 350 + 500,- 400 + + 500,- 400 + 400,-1300 + 500,- 400 + 450,-1300 + 500 -Duration=55000us +Duration=55050us Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM 1=450|1250, 0=450|400 @@ -181,1332 +174,1386 @@ Send with: IrSender.sendPanasonic(0xB, 0x10, ); 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 - + 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 + + 550,- 350 + 450,-1200 + 550,- 350 + 500,- 350 + + 500,- 400 + 500,- 350 + 550,- 300 + 500,- 400 + + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350 + + 500,- 400 + 450,-1200 + 550,- 350 + 500,- 350 + + 550,- 350 + 500,- 350 + 500,- 350 + 500,- 350 + + 500,-1250 + 550,-1150 + 500,- 400 + 500,-1200 + + 550,- 300 + 500,- 400 + 500,- 350 + 500,- 350 + + 550,- 300 + 550,- 350 + 500,- 350 + 550,- 350 + + 500,- 350 + 550,- 350 + 500,- 350 + 550,- 300 + + 500,-1200 + 500,- 400 + 500,- 350 + 550,- 350 + + 450,- 400 + 550,- 300 + 500,- 350 + 550,- 350 + + 500,- 350 + 500,-1200 + 500,- 400 + 500,-1200 + + 500 Duration=54050us -MSB first -Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=780150us, Duration=54100us +Protocol=Panasonic Address=0xB, Command=0x10, Raw-Data=0xA01000B0, 48 bits, LSB first, Gap=780200us, Duration=54050us Send with: IrSender.sendPanasonic(0xB, 0x10, ); rawIRTimings[100]: - -780150 - +3450,-1700 - + 500,- 400 + 500,-1200 + 500,- 350 + 500,- 400 - + 500,- 350 + 550,- 300 + 500,- 400 + 500,- 350 + -780200 + +3500,-1650 + + 550,- 350 + 500,-1200 + 500,- 350 + 550,- 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 + + 550,- 350 + 550,- 300 + 500,- 350 + 550,- 350 + + 550,- 300 + 500,-1200 + 550,- 350 + 450,- 400 + + 500,- 350 + 550,- 300 + 550,- 350 + 500,- 350 + + 550,-1150 + 550,-1150 + 550,- 350 + 450,-1250 + + 500,- 350 + 500,- 400 + 550,- 300 + 500,- 350 + + 550,- 300 + 550,- 350 + 500,- 350 + 500,- 400 + + 500,- 350 + 550,- 350 + 500,- 350 + 500,- 350 + + 550,-1150 + 600,- 300 + 500,- 350 + 500,- 400 + + 450,- 400 + 500,- 350 + 500,- 400 + 500,- 350 + + 500,- 350 + 500,-1200 + 550,- 300 + 550,-1200 + + 500 +Duration=54050us Send 72 bit PulseDistance 0x5A AFEDCBA9 87654321 LSB first 1=550|1700, 0=550|600 -Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=786950us, Duration=139050us +Protocol=PulseDistance, Raw-Data=0x5A, 72 bits, LSB first, Gap=787050us, Duration=139000us Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A}; - IrSender.sendPulseDistanceWidthFromArray(38, 8900, 4400, 650, 1600, 650, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 8850, 4400, 650, 1600, 650, 500, &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 + -787050 + +8850,-4400 + + 600,-1650 + 600,- 550 + 650,- 500 + 650,- 550 + + 650,- 500 + 650,-1600 + 600,- 550 + 650,- 500 + + 650,-1600 + 650,-1600 + 650,- 500 + 650,- 550 + + 600,- 550 + 650,- 500 + 650,-1600 + 650,- 550 + + 600,-1650 + 600,- 550 + 650,-1600 + 650,- 500 + + 650,- 550 + 600,-1650 + 600,-1650 + 650,- 500 + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 550 - + 650,- 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 + + 650,- 550 + 650,- 500 + 600,- 550 + 650,-1650 + + 600,-1650 + 650,- 500 + 650,- 500 + 650,-1650 + + 600,- 550 + 650,-1600 + 650,- 500 + 650,-1600 + + 600,-1650 + 650,-1600 + 650,- 500 + 700,-1550 + + 650,- 550 + 600,- 550 + 650,-1600 + 600,-1650 + + 650,-1600 + 650,- 500 + 600,-1650 + 650,-1600 + + 700,- 450 + 650,-1600 + 650,-1650 + 600,-1650 + + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1650 + + 650,- 500 + 600,-1650 + 600,- 550 + 650,-1650 + + 600,- 550 + 600,-1650 + 600,- 550 + 650,-1600 + + 650,-1600 + 650,- 500 + 600,-1650 + 650,- 550 + 600 -Duration=139050us +Duration=139000us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300 -Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822650us, Duration=49000us +Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=822600us, Duration=48950us Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 700, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 650, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); rawIRTimings[108]: - -822650 + -822600 + 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 + + 400,- 500 + 650,- 300 + 700,- 200 + 650,- 300 + + 650,- 200 + 400,- 550 + 700,- 250 + 700,- 150 + + 400,- 550 + 350,- 600 + 650,- 200 + 700,- 300 + + 600,- 300 + 650,- 250 + 400,- 500 + 650,- 300 + + 350,- 550 + 700,- 200 + 350,- 600 + 650,- 200 + + 750,- 200 + 400,- 550 + 350,- 550 + 650,- 300 + + 350,- 500 + 400,- 550 + 350,- 550 + 650,- 250 + + 650,- 300 + 700,- 250 + 650,- 200 + 400,- 550 + + 350,- 550 + 700,- 250 + 650,- 250 + 350,- 550 + + 650,- 300 + 350,- 550 + 650,- 250 + 400,- 500 + + 350,- 600 + 400,- 500 + 650,- 250 + 350,- 550 + + 700,- 250 + 700,- 200 + 400,- 500 + 400,- 550 + + 350,- 550 + 650,- 250 + 350,- 550 + 350,- 600 + + 350 +Duration=48950us Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600 Protocol=PulseDistance, Raw-Data=0xDCBA9, 52 bits, LSB first, Gap=802900us, Duration=49250us Send on a 8 bit platform with: uint32_t tRawData[]={0x87654321, 0xDCBA9}; - IrSender.sendPulseDistanceWidthFromArray(38, 350, 600, 350, 550, 700, 250, &tRawData[0], 52, PROTOCOL_IS_LSB_FIRST, , ); + IrSender.sendPulseDistanceWidthFromArray(38, 400, 550, 550, 550, 550, 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 + + 400,- 550 + + 350,- 550 + 700,- 250 + 650,- 250 + 650,- 300 + + 650,- 250 + 400,- 500 + 650,- 300 + 600,- 300 + + 350,- 550 + 350,- 550 + 650,- 300 + 650,- 200 + + 750,- 200 + 750,- 100 + 500,- 500 + 650,- 250 + + 400,- 500 + 700,- 200 + 450,- 500 + 700,- 200 + + 700,- 200 + 400,- 550 + 400,- 500 + 700,- 200 + + 400,- 550 + 350,- 550 + 350,- 550 + 700,- 250 + + 650,- 200 + 700,- 250 + 700,- 200 + 400,- 550 + + 400,- 500 + 700,- 200 + 750,- 200 + 400,- 500 + + 700,- 200 + 400,- 550 + 650,- 250 + 350,- 550 + + 350,- 600 + 350,- 550 + 650,- 200 + 400,- 550 + + 650,- 300 + 650,- 250 + 400,- 500 + 400,- 550 + + 400,- 500 + 650,- 300 + 300,- 550 + 400,- 550 + 700 Duration=49250us Send 7 bit ASCII character with PulseDistanceWidth LSB first 1=500|1500, 0=1500|500 -Protocol=PulseDistance, Raw-Data=0x76, 7 bits, LSB first, Gap=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]: - -800750 - +6000,- 450 - +1550,- 450 + 500,-1450 + 550,-1450 +1550,- 450 - + 550,-1450 + 550,-1450 + 550,-1450 + 550 -Duration=20950us +Protocol=PulseDistance, Raw-Data=0x76, 7 bits, LSB first, Gap=800900us, Duration=21050us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 5950, 500, 550, 1450, 1600, 450, 0x76, 7, PROTOCOL_IS_LSB_FIRST, , ); +rawIRTimings[18]: + -800900 + +5950,- 500 + +1550,- 450 + 550,-1450 + 600,-1400 +1600,- 400 + + 550,-1450 + 550,-1450 + 550,-1450 + 600 +Duration=21050us Send Velux 0x654321 decoded as PulseDistanceWidth 0x3D9EAC LSB first 1=1275|475, 0=475|1275 -Protocol=PulseDistance, Raw-Data=0x3D9EAC, 23 bits, LSB first, Gap=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 +Protocol=PulseDistance, Raw-Data=0x3D9EAC, 23 bits, LSB first, Gap=747800us, Duration=42450us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 550, 1250, 450, 1250, 1300, 400, 0x3D9EAC, 23, PROTOCOL_IS_LSB_FIRST, , ); +rawIRTimings[50]: + -747800 + 550,-1250 - +1300,- 400 +1300,- 400 + 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 + +1300,- 400 +1300,- 400 + 500,-1200 + 450,-1250 + +1350,- 400 + 450,-1250 +1300,- 400 + 450,-1250 + +1300,- 400 + 450,-1250 + 500,-1200 + 500,-1250 + + 450,-1250 +1300,- 400 +1350,- 350 + 500,-1200 + + 450,-1300 +1300,- 400 + 450,-1250 + 450,-1250 + + 500,-1200 + 450,-1250 +1350,- 400 +1350 +Duration=42450us Send Sony12 as PulseWidth LSB first 1=1200|300, 0=600|600 -Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=744650us, Duration=21050us -Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: - -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 -Duration=21050us +Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=762850us, Duration=21150us +Send with: IrSender.sendSony(0x11, 0x76, , 12); +rawIRTimings[26]: + -762850 + +2450,- 550 + + 700,- 500 +1300,- 500 +1250,- 550 + 700,- 500 + +1300,- 550 +1250,- 550 +1250,- 550 +1250,- 550 + + 700,- 550 + 650,- 550 + 700,- 500 +1250 +Duration=21150us -Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 -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]: - -744500 +Send 32 bit PulseWidth 0x87654321 LSB first 1=600|300, 0=300|300 - timing ratio is 1:2 +Protocol=PulseWidth, Raw-Data=0x87654321, 32 bits, LSB first, Gap=748050us, Duration=24950us +Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 1050, 500, 700, 250, 400, 250, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, , ); +rawIRTimings[66]: + -748050 +1050,- 500 - + 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 - + 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 + + 650,- 250 + 400,- 200 + 400,- 200 + 450,- 200 + + 350,- 300 + 650,- 200 + 400,- 250 + 400,- 200 + + 700,- 250 + 700,- 200 + 400,- 250 + 350,- 250 + + 350,- 300 + 300,- 300 + 650,- 250 + 400,- 200 + + 700,- 250 + 350,- 250 + 700,- 250 + 350,- 250 + + 400,- 150 + 750,- 150 + 750,- 250 + 350,- 250 + + 700,- 200 + 700,- 250 + 700,- 150 + 400,- 300 + + 350,- 250 + 400,- 150 + 400,- 250 + 700 +Duration=24950us Send MagiQuest 0x6BCDFF00, 0x176 as 55 bit PulseDistanceWidth MSB first 1=576|576, 0=287|864 -Protocol=MagiQuest Address=0xFF00, Command=0x176, Raw-Data=0x6BCDFF00, 56 bits, MSB first, Gap=773750us, Duration=63850us +Protocol=MagiQuest Address=0xFF00, Command=0x176, Raw-Data=0x6BCDFF00, 56 bits, MSB first, Gap=774150us, Duration=64900us Send with: IrSender.sendMagiQuest(0x6BCDFF00, 0x176, ); -rawData[112]: - -773750 - + 350,- 850 + 300,- 850 + 300,- 800 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 800 - + 650,- 500 + 600,- 550 + 350,- 800 + 600,- 550 - + 350,- 800 + 600,- 550 + 600,- 550 + 600,- 550 - + 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 + 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 -Duration=63850us +rawIRTimings[112]: + -774150 + + 350,- 850 + 350,- 800 + 400,- 800 + 350,- 800 + + 450,- 700 + 400,- 800 + 400,- 750 + 400,- 800 + + 650,- 500 + 600,- 550 + 400,- 750 + 600,- 600 + + 350,- 800 + 600,- 600 + 650,- 500 + 650,- 500 + + 650,- 550 + 350,- 800 + 400,- 800 + 600,- 550 + + 650,- 500 + 400,- 800 + 650,- 500 + 600,- 550 + + 600,- 550 + 700,- 500 + 600,- 550 + 650,- 550 + + 550,- 600 + 600,- 550 + 650,- 550 + 350,- 800 + + 350,- 850 + 400,- 750 + 400,- 800 + 350,- 800 + + 350,- 800 + 350,- 850 + 350,- 800 + 600,- 550 + + 350,- 850 + 600,- 550 + 650,- 550 + 600,- 550 + + 350,- 800 + 600,- 600 + 600,- 550 + 350,- 800 + + 350,- 850 + 350,- 800 + 350,- 800 + 600,- 600 + + 650,- 500 + 400,- 750 + 400,- 800 + 600 +Duration=64900us Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xFFF1, Command=0x7776, Raw-Data=0x7776FFF1, 32 bits, LSB first, Gap=790650us, Duration=76650us +Protocol=Onkyo Address=0xFFF1, Command=0x7776, Raw-Data=0x7776FFF1, 32 bits, LSB first, Gap=791150us, Duration=76750us Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); -rawData[68]: - -790650 - +8950,-4400 - + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 - + 600,-1600 + 650,-1600 + 650,-1600 + 650,-1600 +rawIRTimings[68]: + -791150 + +8900,-4450 + + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500 + 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,-1650 + 650,-1550 + 650,-1600 + 600,-1650 + + 650,-1600 + 600,-1600 + 650,-1600 + 600,-1650 + + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 700,- 450 + + 600,-1650 + 600,-1600 + 700,-1550 + 600,- 550 + 600 -Duration=76650us +Duration=76750us Send Apple -Protocol=Apple Address=0xF1, Command=0x76, Raw-Data=0xF17687EE, 32 bits, LSB first, Gap=763800us, Duration=72250us +Protocol=Apple Address=0xF1, Command=0x76, Raw-Data=0xF17687EE, 32 bits, LSB first, Gap=764350us, Duration=72350us Send with: IrSender.sendApple(0xF1, 0x76, ); -rawData[68]: - -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 +rawIRTimings[68]: + -764350 + +8900,-4450 + + 600,- 500 + 600,-1650 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,-1600 + 600,-1650 + 650,-1600 + + 600,-1650 + 650,-1600 + 600,-1650 + 600,- 500 + + 650,- 500 + 600,- 550 + 600,- 500 + 650,-1600 + + 650,- 500 + 650,-1600 + 600,-1600 + 600,- 550 + + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500 + + 650,-1600 + 600,- 550 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650 + 600 -Duration=72250us +Duration=72350us Send Panasonic -Protocol=Panasonic Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=763550us, Duration=64400us +Protocol=Panasonic Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=764050us, Duration=65300us Send with: IrSender.sendPanasonic(0xFF1, 0x76, ); -rawData[100]: - -763550 - +3450,-1700 - + 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 -Duration=64400us - - -Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xFF1, Command=0x76, Extra=0x4711, Raw-Data=0x9A76FF13, 48 bits, LSB first, Gap=783450us, Duration=69550us +rawIRTimings[100]: + -764050 + +3500,-1700 + + 450,- 400 + 500,-1250 + 500,- 400 + 500,- 400 + + 450,- 450 + 500,- 350 + 500,- 400 + 500,- 350 + + 550,- 350 + 500,- 400 + 500,- 400 + 500,- 350 + + 450,- 450 + 500,-1250 + 450,- 400 + 500,- 400 + + 500,- 400 + 500,- 400 + 400,- 450 + 500,- 400 + + 400,-1350 + 500,- 400 + 500,- 400 + 500,- 350 + + 550,-1200 + 500,-1250 + 450,-1250 + 500,-1250 + + 500,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 500,- 400 + 500,-1250 + 500,-1250 + 500,- 350 + + 550,-1200 + 500,-1250 + 500,-1250 + 500,- 400 + + 450,-1250 + 500,- 400 + 500,- 400 + 450,-1300 + + 450,-1250 + 550,- 350 + 500,- 400 + 500,-1250 + + 500 +Duration=65300us + + +Send Kaseikyo with extra=0x4711 as Vendor ID +Protocol=Kaseikyo Address=0xFF1, Command=0x76, Extra=0x4711, Raw-Data=0x9A76FF13, 48 bits, LSB first, Gap=784400us, Duration=70450us Send with: IrSender.sendKaseikyo(0xFF1, 0x76, , 0x4711); -rawData[100]: - -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 + 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 +rawIRTimings[100]: + -784400 + +3450,-1700 + + 550,-1200 + 500,- 400 + 450,- 450 + 500,- 350 + + 500,-1250 + 450,- 450 + 450,- 450 + 500,- 400 + + 500,-1200 + 500,-1250 + 500,-1250 + 500,- 400 + + 450,- 400 + 550,- 350 + 500,-1250 + 500,- 400 + + 500,-1200 + 450,-1300 + 500,- 400 + 500,- 400 + + 450,-1250 + 500,- 400 + 500,- 400 + 450,- 450 + + 450,-1250 + 500,-1250 + 500,-1250 + 500,-1250 + + 450,-1300 + 500,-1200 + 500,-1250 + 500,-1250 + + 500,- 400 + 500,-1250 + 450,-1250 + 500,- 400 + + 500,-1250 + 500,-1250 + 450,-1250 + 500,- 400 + + 550,- 350 + 450,-1300 + 500,- 400 + 500,-1250 + + 450,-1250 + 550,- 350 + 500,- 400 + 500,-1250 + + 500 +Duration=70450us Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=784200us, Duration=67850us +Protocol=Kaseikyo_Denon Address=0xFF1, Command=0x76, Raw-Data=0x9976FF10, 48 bits, LSB first, Gap=784650us, Duration=68700us Send with: IrSender.sendKaseikyo_Denon(0xFF1, 0x76, ); -rawData[100]: - -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 - + 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 +rawIRTimings[100]: + -784650 + +3550,-1650 + + 500,- 400 + 500,- 400 + 450,-1250 + 500,- 400 + + 450,-1300 + 450,- 450 + 500,-1200 + 500,- 400 + + 450,- 450 + 450,-1250 + 500,- 400 + 450,- 450 + + 500,-1250 + 500,-1250 + 500,- 400 + 500,- 350 + + 500,- 400 + 500,- 400 + 500,- 400 + 500,- 350 + + 500,-1250 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,-1250 + 450,-1250 + 450,-1300 + 500,-1250 + + 500,-1250 + 500,-1250 + 450,-1250 + 550,-1200 + + 500,- 400 + 500,-1250 + 500,-1250 + 500,- 400 + + 450,-1250 + 500,-1250 + 450,-1300 + 450,- 400 + + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250 + + 500,-1250 + 500,- 400 + 450,- 400 + 500,-1250 + 500 -Duration=67850us +Duration=68700us -Send Denon with repeats -Protocol=Denon Address=0x11, Command=0x76, Raw-Data=0xED1, 15 bits, LSB first, Gap=783000us, Duration=23100us +Send Denon with 2 autorepeats after 45 ms +Protocol=Denon Address=0x11, Command=0x76, Raw-Data=0xED1, 15 bits, LSB first, Gap=784950us, Duration=23450us Send with: IrSender.sendDenon(0x11, 0x76, ); -rawData[32]: - -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 -Duration=23100us +rawIRTimings[32]: + -784950 + + 350,-1750 + 350,- 700 + 300,- 800 + 300,- 750 + + 300,-1750 + 350,- 750 + 300,-1750 + 350,-1750 + + 300,- 750 + 350,-1750 + 350,-1750 + 300,-1800 + + 300,- 750 + 300,- 750 + 300,- 750 + 350 +Duration=23450us -Send Denon/Sharp variant with repeats -Protocol=Sharp Address=0x11, Command=0x76, Raw-Data=0x2ED1, 15 bits, LSB first, Gap=726000us, Duration=24150us +Send Denon/Sharp variant with 2 autorepeat5 after 45 ms +Protocol=Sharp Address=0x11, Command=0x76, Raw-Data=0x2ED1, 15 bits, LSB first, Gap=728000us, Duration=24400us Send with: IrSender.sendSharp(0x11, 0x76, ); -rawData[32]: - -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,-1750 + 300,- 750 + 300 -Duration=24150us +rawIRTimings[32]: + -728000 + + 350,-1750 + 300,- 750 + 300,- 750 + 300,- 750 + + 350,-1750 + 300,- 750 + 300,-1800 + 350,-1700 + + 300,- 750 + 350,-1750 + 350,-1750 + 300,-1800 + + 350,- 700 + 350,-1700 + 300,- 800 + 300 +Duration=24400us Send Sony/SIRCS with 7 command and 5 address bits -Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=727100us, Duration=21050us -Send with: IrSender.sendSony(0x11, 0x76, 2, 12); -rawData[26]: - -727100 - +2450,- 550 - + 650,- 550 +1250,- 550 +1250,- 550 + 650,- 550 - +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 - + 650,- 550 + 650,- 550 + 600,- 600 +1250 -Duration=21050us +Protocol=Sony Address=0x11, Command=0x76, Raw-Data=0x8F6, 12 bits, LSB first, Gap=727550us, Duration=21250us +Send with: IrSender.sendSony(0x11, 0x76, , 12); +rawIRTimings[26]: + -727550 + +2500,- 550 + + 650,- 550 +1250,- 550 +1250,- 550 + 700,- 500 + +1250,- 600 +1250,- 550 +1250,- 550 +1300,- 500 + + 650,- 550 + 700,- 550 + 650,- 550 +1300 +Duration=21250us Send Sony/SIRCS with 7 command and 8 address bits -Protocol=Sony Address=0xF1, Command=0x76, Raw-Data=0x78F6, 15 bits, LSB first, Gap=743250us, Duration=26450us -Send with: IrSender.sendSony(0xF1, 0x76, 2, 15); -rawData[32]: - -743250 +Protocol=Sony Address=0xF1, Command=0x76, Raw-Data=0x78F6, 15 bits, LSB first, Gap=744950us, Duration=26650us +Send with: IrSender.sendSony(0xF1, 0x76, , 15); +rawIRTimings[32]: + -744950 +2400,- 600 - + 650,- 550 +1200,- 600 +1250,- 550 + 650,- 550 - +1250,- 550 +1250,- 550 +1250,- 550 +1250,- 550 - + 650,- 550 + 650,- 550 + 650,- 550 +1250,- 550 + + 700,- 500 +1250,- 600 +1300,- 500 + 700,- 500 + +1250,- 550 +1300,- 550 +1250,- 550 +1250,- 550 + + 700,- 550 + 600,- 600 + 650,- 550 +1250,- 600 +1250,- 550 +1250,- 550 +1250 -Duration=26450us +Duration=26650us -Send Sony/SIRCS with 7 command and 13 address bits -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]: - -746700 - +2400,- 600 - + 600,- 600 +1200,- 550 +1250,- 550 + 700,- 500 - +1250,- 550 +1250,- 550 +1250,- 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 -Duration=35400us +Send Sony/SIRCS with 7 command and 13 address bits and no repeats +Protocol=Sony Address=0x1FF1, Command=0x76, Raw-Data=0xFF8F6, 20 bits, LSB first, Gap=749650us, Duration=35650us +Send with: IrSender.sendSony(0x1FF1, 0x76, , 20); +rawIRTimings[42]: + -749650 + +2450,- 550 + + 650,- 550 +1250,- 550 +1250,- 550 + 700,- 550 + +1300,- 500 +1250,- 550 +1300,- 500 +1250,- 550 + + 700,- 550 + 650,- 550 + 700,- 500 +1250,- 550 + +1250,- 550 +1250,- 550 +1250,- 600 +1250,- 550 + +1250,- 550 +1250,- 550 +1250,- 550 +1300 +Duration=35650us Send Samsung 8 bit command and 8 bit address -Protocol=Samsung Address=0xF1, Command=0x76, Raw-Data=0x8976F1F1, 32 bits, LSB first, Gap=751750us, Duration=65600us +Protocol=Samsung Address=0xF1, Command=0x76, Raw-Data=0x8976F1F1, 32 bits, LSB first, Gap=753500us, Duration=65700us Send with: IrSender.sendSamsung(0xF1, 0x76, ); -rawData[68]: - -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 +rawIRTimings[68]: + -753500 + +4500,-4400 + + 600,-1650 + 600,- 550 + 600,- 500 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 600,- 550 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + 650,- 500 + 600,-1650 + 600,-1600 + 650,- 500 - + 600,-1650 + 600,-1650 + 600,-1600 + 600,- 550 - + 600,-1650 + 600,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500 + + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 600,- 550 + 600,- 550 + 600,-1600 + 650 -Duration=65600us +Duration=65700us + + +Send Samsung 8 bit command and 16 bit address +Protocol=Samsung Address=0xFFF1, Command=0x76, Raw-Data=0x8976FFF1, 32 bits, LSB first, Gap=766950us, Duration=68950us +Send with: IrSender.sendSamsung(0xFFF1, 0x76, ); +rawIRTimings[68]: + -766950 + +4450,-4450 + + 650,-1600 + 650,- 500 + 600,- 500 + 600,- 500 + + 650,-1600 + 600,-1650 + 600,-1650 + 650,-1600 + + 600,-1600 + 650,-1600 + 650,-1600 + 600,-1650 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,-1600 + + 650,- 500 + 650,-1600 + 600,-1600 + 650,- 500 + + 600,-1650 + 600,-1650 + 650,-1550 + 650,- 500 + + 600,-1650 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,- 500 + 650,- 500 + 650,- 450 + 650,-1600 + + 600 +Duration=68950us Send Samsung 16 bit command and address -Protocol=Samsung Address=0xFFF1, Command=0x9876, Raw-Data=0x9876FFF1, 32 bits, LSB first, Gap=766100us, Duration=68950us +Protocol=Samsung Address=0xFFF1, Command=0x9876, Raw-Data=0x9876FFF1, 32 bits, LSB first, Gap=766800us, Duration=69050us Send with: IrSender.sendSamsung(0xFFF1, 0x9876, ); -rawData[68]: - -766100 +rawIRTimings[68]: + -766800 +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 + + 600,-1650 + 600,- 550 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1650 + 600,-1600 + + 600,-1650 + 650,-1600 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,-1600 + 650,-1600 + 600,- 550 + + 600,-1650 + 600,-1600 + 650,-1600 + 700,- 450 + + 600,- 550 + 600,- 500 + 700,- 450 + 650,-1600 + + 600,-1650 + 600,- 500 + 600,- 550 + 600,-1650 + + 600 +Duration=69050us Send Samsung48 16 bit command -Protocol=Samsung48 Address=0xFFF1, Command=0x9876, Raw-Data=0x6798, 48 bits, LSB first, Gap=765950us, Duration=95900us +Protocol=Samsung48 Address=0xFFF1, Command=0x9876, Raw-Data=0x6798, 48 bits, LSB first, Gap=766300us, Duration=96000us Send with: IrSender.sendSamsung48(0xFFF1, 0x9876, ); -rawData[100]: - -765950 - +4500,-4450 - + 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 +rawIRTimings[100]: + -766300 + +4500,-4400 + + 650,-1600 + 600,- 500 + 650,- 500 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,-1600 + + 600,-1650 + 600,-1650 + 650,-1600 + 600,-1600 + + 650,- 500 + 600,-1650 + 650,-1600 + 600,- 500 + + 600,-1650 + 650,-1600 + 650,-1600 + 600,- 500 + + 650,-1600 + 650,- 500 + 650,- 450 + 650,-1600 + + 650,- 500 + 650,- 450 + 650,- 500 + 600,-1650 + + 650,- 500 + 600,- 550 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,- 500 + 600,- 550 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 500 + 600 -Duration=95900us +Duration=96000us Send RC5 -Protocol=RC5 Address=0x11, Command=0x36, Raw-Data=0x1476, 13 bits, MSB first, Gap=782100us, Duration=23150us +Protocol=RC5 Address=0x11, Command=0x36, Raw-Data=0x1476, 13 bits, MSB first, Gap=782400us, Duration=23300us Send with: IrSender.sendRC5(0x11, 0x36, ); -rawData[20]: - -782100 - + 900,- 850 - +1850,-1700 +1850,- 850 + 900,- 850 + 950,-1700 - + 950,- 850 + 950,- 850 +1800,-1700 + 950,- 850 - +1850 -Duration=23150us +rawIRTimings[20]: + -782400 + + 950,- 850 + +1850,-1700 +1850,- 850 + 900,- 850 +1000,-1700 + + 950,- 850 + 900,- 850 +1850,-1750 + 900,- 850 + +1900 +Duration=23300us Send RC5X with 7.th MSB of command set -Protocol=RC5 Address=0x11, Command=0x76, Toggle=1, Raw-Data=0xC76, 13 bits, MSB first, Gap=742250us, Duration=23100us +Protocol=RC5 Address=0x11, Command=0x76, Toggle=1, Raw-Data=0xC76, 13 bits, MSB first, Gap=742050us, Duration=23250us Send with: IrSender.sendRC5(0x11, 0x76, ); -rawData[20]: - -742250 - +1800,-1700 - + 950,- 850 +1800,- 850 + 950,- 850 + 950,-1700 - + 950,- 850 + 900,- 850 +1850,-1700 + 950,- 850 - +1800 -Duration=23100us +rawIRTimings[20]: + -742050 + +1800,-1750 + + 950,- 800 +1900,- 800 + 900,- 850 +1000,-1700 + +1000,- 800 + 900,- 850 +1900,-1650 +1000,- 800 + +1900 +Duration=23250us + + +Send Marantz with RC5 and extra=0x9 +Protocol=Marantz Address=0x11, Command=0x36, Extra=0x9, Raw-Data=0x51D89, 19 bits, MSB first, Gap=742600us, Duration=38400us +Send with: IrSender.sendMarantz(0x11, 0x36, , 0x9); +rawIRTimings[30]: + -742600 + + 900,- 850 + +1850,-1750 +1800,- 850 + 900,- 850 +1000,-1700 + +1000,-4350 + 950,- 850 +1800,-1750 + 950,- 800 + +1850,- 850 + 900,- 900 + 900,-1750 +1850,- 800 + +1000,-1700 +1000 +Duration=38400us + + +Send Marantz with RC5A and extra=0x9 +Protocol=Marantz Address=0x11, Command=0x76, Extra=0x9, Toggle=1, Raw-Data=0x31D89, 19 bits, MSB first, Gap=748550us, Duration=38400us +Send with: IrSender.sendMarantz(0x11, 0x76, , 0x9); +rawIRTimings[30]: + -748550 + +1800,-1800 + + 950,- 850 +1800,- 800 +1000,- 800 +1000,-1700 + + 950,-4400 + 900,- 850 +1850,-1750 + 950,- 850 + +1800,- 850 + 950,- 850 + 950,-1700 +1800,- 850 + +1000,-1750 + 900 +Duration=38400us Send RC6 -Protocol=RC6 Address=0xF1, Command=0x76, Raw-Data=0xF176, 20 bits, MSB first, Gap=739650us, Duration=23300us +Protocol=RC6 Address=0xF1, Command=0x76, Raw-Data=0xF176, 20 bits, MSB first, Gap=746200us, Duration=23600us Send with: IrSender.sendRC6(0xF1, 0x76, ); -rawData[36]: - -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 -Duration=23300us +rawIRTimings[36]: + -746200 + +2700,- 800 + + 600,- 750 + 550,- 400 + 550,- 350 + 500,- 850 + +1400,- 400 + 550,- 350 + 550,- 400 + 500,- 850 + + 500,- 400 + 550,- 350 + 950,- 900 + 950,- 400 + + 550,- 400 + 500,- 850 +1000,- 350 + 550,- 800 + + 550 +Duration=23600us -Send RC6A with 14 bit 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 RC6A with 14 bit and extra=0x2711 +Protocol=RC6A Address=0xF1, Command=0x76, Extra=0x2711, Toggle=1, Raw-Data=0xA711F176, 35 bits, MSB first, Gap=749050us, Duration=37450us Send with: IrSender.sendRC6A(0xF1, 0x76, , 0x2711); -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 +rawIRTimings[58]: + -749050 + +2700,- 850 + + 500,- 400 + 550,- 350 + 500,- 850 +1450,-1300 + +1000,- 850 + 500,- 400 +1000,- 400 + 500,- 450 + + 500,- 800 + 500,- 400 + 500,- 450 + 950,- 850 + + 500,- 450 + 500,- 400 +1000,- 400 + 500,- 400 + + 500,- 400 + 500,- 400 + 550,- 850 + 500,- 400 + + 500,- 400 +1050,- 800 +1000,- 400 + 500,- 400 + + 500,- 850 +1000,- 400 + 500,- 850 + 550 +Duration=37450us Send MagiQuest, WandId=0x6BCDFFF1 -Protocol=MagiQuest Address=0xFFF1, Command=0x76, Raw-Data=0x6BCDFFF1, 56 bits, MSB first, Gap=765200us, Duration=64000us +Protocol=MagiQuest Address=0xFFF1, Command=0x76, Raw-Data=0x6BCDFFF1, 56 bits, MSB first, Gap=763750us, Duration=65050us Send with: IrSender.sendMagiQuest(0x6BCDFFF1, 0x76, ); -rawData[112]: - -765200 - + 350,- 800 + 350,- 800 + 300,- 850 + 350,- 800 - + 350,- 800 + 350,- 800 + 350,- 800 + 350,- 850 - + 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 - + 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,- 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 -Duration=64000us - - -Send OpenLASIR mode fire and color orange -Protocol=Onkyo Address=0xF1, Command=0x6076, Raw-Data=0x60760EF1, 32 bits, LSB first, Gap=791350us, Duration=66750us -Send with: IrSender.sendOnkyo(0xF1, 0x6076, ); +rawIRTimings[112]: + -763750 + + 350,- 800 + 400,- 800 + 350,- 800 + 400,- 750 + + 400,- 800 + 350,- 800 + 350,- 850 + 350,- 850 + + 600,- 600 + 650,- 500 + 350,- 800 + 600,- 600 + + 350,- 800 + 650,- 500 + 650,- 550 + 650,- 500 + + 650,- 550 + 350,- 800 + 400,- 750 + 650,- 550 + + 600,- 550 + 400,- 800 + 600,- 550 + 650,- 500 + + 600,- 600 + 650,- 500 + 650,- 500 + 650,- 550 + + 600,- 550 + 650,- 550 + 600,- 550 + 600,- 550 + + 650,- 500 + 600,- 600 + 600,- 550 + 350,- 800 + + 400,- 800 + 400,- 750 + 650,- 550 + 350,- 800 + + 350,- 850 + 650,- 500 + 650,- 550 + 600,- 550 + + 350,- 800 + 650,- 550 + 600,- 550 + 350,- 850 + + 350,- 800 + 350,- 850 + 650,- 500 + 650,- 550 + + 350,- 800 + 650,- 500 + 650,- 550 + 650 +Duration=65050us + + +Send OpenLASIR mode fire and color orange, detected as ONKYO +Protocol=Onkyo Address=0xF1, Command=0xC076, Raw-Data=0xC0760EF1, 32 bits, LSB first, Gap=792950us, Duration=66750us +Send with: IrSender.sendOnkyo(0xF1, 0xC076, ); rawIRTimings[68]: - -791350 - +8900,-4450 - + 600,-1650 + 650,- 450 + 600,- 550 + 650,- 500 - + 650,-1550 + 650,-1600 + 650,-1600 + 650,-1600 + -792950 + +8950,-4400 + + 600,-1650 + 600,- 500 + 600,- 550 + 650,- 500 + + 600,-1600 + 650,-1600 + 600,-1650 + 600,-1650 + 600,- 500 + 650,-1600 + 650,-1600 + 600,-1650 - + 650,- 450 + 600,- 550 + 600,- 550 + 600,- 500 - + 650,- 500 + 600,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,- 500 + + 600,- 550 + 600,-1600 + 600,-1650 + 600,- 550 + 600,-1650 + 600,-1600 + 650,-1600 + 650,- 500 - + 600,- 500 + 600,- 550 + 650,- 500 + 650,- 450 - + 600,- 550 + 600,-1650 + 650,-1600 + 600,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 650,- 500 + 650,- 500 + 600,-1600 + 600,-1650 + 600 Duration=66750us Send Lego with 2 channel and with 4 command bits -Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169, 16 bits, MSB first, Gap=791500us, Duration=9950us +Protocol=Lego Address=0x1, Command=0x16, Raw-Data=0x1169, 16 bits, MSB first, Gap=767200us, Duration=10250us Send with: IrSender.sendLego(0x1, 0x16, ); -rawData[36]: - -791500 +rawIRTimings[36]: + -767200 + 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 + + 250,- 500 + 250,- 150 + 200,- 300 + 200,- 500 + + 250,- 150 + 200,- 600 + 250,- 500 + 200,- 150 + + 300,- 500 + 200,- 200 + 250,- 200 + 200,- 300 + + 250,- 450 + 250,- 150 + 200,- 300 + 250,- 150 + + 250 +Duration=10250us -Send Bang&Olufsen / originally with 455 kHz +Send 16 bit Bang&Olufsen / originally with 455 kHz - ENABLE_BEO_WITHOUT_FRAME_GAP is enabled -rawData[44]: - -748300 +rawIRTimings[44]: + -749450 + 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 + + 300,-2850 + 250,-12750 + 250,-2850 + 250,-9050 + + 250,-5950 + 250,-5950 + 300,-5950 + 250,-2850 + + 250,-5950 + 300,-5900 + 300,-9000 + 250,-2900 + + 250,-9050 + 250,-5950 + 300,-5900 + 300,-2850 + + 300,-9000 + 250,-5950 + 250,-2850 + 300,-12100 + + 300 +Duration=134400us - Now try to decode the first 6 entries, which results in rawData 0x0 -Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=748300us, Duration=6450us +Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=749450us, Duration=6500us - Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode -Protocol=Bang&Olufsen Address=0xF1, Command=0x76, Raw-Data=0xF176, 16 bits, MSB first, Gap=12750us, Duration=115000us +Protocol=Bang&Olufsen Address=0xF1, Command=0x76, Raw-Data=0xF176, 16 bits, MSB first, Gap=12750us, Duration=115150us Send with: IrSender.sendBang&Olufsen(0xF1, 0x76, ); -rawData[38]: +rawIRTimings[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 + + 250,-2850 + + 250,-9050 + 250,-5950 + 250,-5950 + 300,-5950 + + 250,-2850 + 250,-5950 + 300,-5900 + 300,-9000 + + 250,-2900 + 250,-9050 + 250,-5950 + 300,-5900 + + 300,-2850 + 300,-9000 + 250,-5950 + 250,-2850 + + 300,-12100 + 300 +Duration=115150us Send next protocols with IrSender.write Send JVC -Protocol=JVC Address=0xF1, Command=0x76, Raw-Data=0x76F1, 16 bits, LSB first, Gap=804700us, Duration=40450us +Protocol=JVC Address=0xF1, Command=0x76, Raw-Data=0x76F1, 16 bits, LSB first, Gap=805500us, Duration=40700us Send with: IrSender.sendJVC(0xF1, 0x76, ); -rawData[36]: - -804700 - +8400,-4150 - + 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 +rawIRTimings[36]: + -805500 + +8450,-4100 + + 650,-1500 + 600,- 450 + 600,- 450 + 600,- 500 + + 550,-1550 + 600,-1500 + 600,-1500 + 550,-1600 + + 550,- 500 + 600,-1500 + 600,-1500 + 600,- 500 + + 550,-1550 + 600,-1500 + 600,-1500 + 600,- 500 + 600 -Duration=40450us +Duration=40700us Send LG -Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745550us, Duration=59450us +Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745850us, Duration=59800us Send with: IrSender.sendLG(0xF1, 0x9876, ); -rawData[60]: - -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 +rawIRTimings[60]: + -745850 + +8950,-4150 + + 550,-1500 + 550,-1550 + 550,-1550 + 550,-1500 + + 600,- 500 + 550,- 500 + 600,- 450 + 550,-1550 + + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550 + + 550,-1550 + 600,- 450 + 550,- 500 + 550,- 500 + + 550,- 550 + 550,-1550 + 550,-1500 + 600,-1500 + + 550,- 500 + 550,-1550 + 600,-1500 + 550,- 500 + + 600,-1500 + 550,-1550 + 550,-1500 + 600,- 500 + 550 -Duration=59450us +Duration=59800us Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=762100us, Duration=26800us +Protocol=BoseWave Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=762400us, Duration=27150us Send with: IrSender.sendBoseWave(0x0, 0x76, ); -rawData[36]: - -762100 - +1050,-1450 - + 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 -Duration=26800us +rawIRTimings[36]: + -762400 + +1100,-1400 + + 600,- 450 + 550,-1400 + 600,-1400 + 600,- 450 + + 550,-1400 + 600,-1400 + 600,-1400 + 600,- 450 + + 550,-1400 + 600,- 450 + 550,- 400 + 650,-1350 + + 600,- 450 + 550,- 450 + 550,- 450 + 600,-1400 + + 600 +Duration=27150us Send FAST -Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=746450us, Duration=28900us +Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=746700us, Duration=29250us Send with: IrSender.sendFAST(0x0, 0x76, ); -rawData[36]: - -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 +rawIRTimings[36]: + -746700 + +2200,-1000 + + 600,- 450 + 600,-1550 + 550,-1550 + 600,- 450 + + 600,-1500 + 600,-1550 + 550,-1550 + 550,- 500 + + 600,-1500 + 600,- 500 + 550,- 500 + 600,-1550 + + 550,- 500 + 600,- 450 + 600,- 500 + 550,-1550 + + 600 +Duration=29250us 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]: - -745700 - + 200,- 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,- 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 - + 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,- 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 -Duration=149500us - -ERROR: Unknown protocol - +rawIRTimings[400]: + -745550 + + 250,- 550 + + 250,- 500 + 300,- 500 + 300,- 450 + 300,- 450 + + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500 + + 300,- 450 + 250,- 500 + 300,- 500 + 250,- 500 + + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550 + + 200,- 550 + 200,- 550 + 200,- 550 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 300,- 450 + + 300,- 450 + 300,- 500 + 200,- 550 + 200,- 550 + + 300,- 500 + 200,- 550 + 300,- 500 + 250,- 500 + + 300,- 500 + 200,- 550 + 200,- 550 + 250,- 500 + + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 500 + + 300,- 450 + 250,- 500 + 300,- 500 + 250,- 500 + + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 500 + + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500 + + 200,- 550 + 200,- 550 + 300,- 500 + 250,- 500 + + 200,- 600 + 250,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 500 + 300,- 500 + 200,- 550 + + 200,- 550 + 250,- 550 + 250,- 500 + 200,- 550 + + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500 + + 250,- 500 + 250,- 550 + 200,- 550 + 200,- 550 + + 250,- 550 + 250,- 500 + 250,- 500 + 200,- 600 + + 250,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500 + + 300,- 500 + 250,- 500 + 300,- 450 + 250,- 500 + + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500 + + 200,- 550 + 300,- 500 + 200,- 550 + 250,- 500 + + 300,- 500 + 300,- 450 + 300,- 450 + 300,- 500 + + 300,- 450 + 200,- 550 + 300,- 500 + 250,- 500 + + 250,- 500 + 250,- 550 + 250,- 500 + 300,- 450 + + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 300,- 450 + + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500 + + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 550 + 250,- 500 + + 250,- 500 + 250,- 550 + 250,- 500 + 300,- 500 + + 250,- 500 + 250,- 500 + 250,- 550 + 200,- 550 + + 250,- 500 + 250,- 550 + 250,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 550 + + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500 + + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550 + + 200,- 600 + 200,- 500 + 250,- 550 + 200,- 550 + + 250,- 550 + 200,- 550 + 250,- 550 + 200,- 550 + + 200,- 550 + 250,- 500 + 250,- 550 + 200,- 600 + + 200,- 550 + 200,- 550 + 250,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 600 + + 200,- 550 + 200,- 550 + 200,- 550 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 550 + 200,- 550 + + 250,- 550 + 200,- 550 + 200 +Duration=152950us + +Invert toggle value for next loop Stop receiver Start receiver address=0xF2 command=0x87 repeats=1 Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2 -Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=923450us, Duration=67850us +Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=915400us, Duration=67850us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -923450 - +8950,-4400 - + 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 +rawIRTimings[68]: + -915400 + +8900,-4450 + + 600,- 500 + 600,-1650 + 700,- 450 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 600,-1650 + 650,- 500 + 600,-1650 + 600,-1600 + + 650,- 500 + 600,- 550 + 650,- 450 + 650,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500 + + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600 + + 650,- 450 + 600,- 550 + 600,- 500 + 650,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 600 Duration=67850us -Protocol=NEC2 Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Repeat, Gap=68700us, Duration=67800us +Protocol=NEC2 Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Repeat, Gap=69250us, Duration=67900us Send with: IrSender.sendNEC2(0xF2, 0x87, ); -rawData[68]: - -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 +rawIRTimings[68]: + -69250 + +8900,-4450 + + 600,- 500 + 650,-1600 + 700,- 450 + 600,- 500 + + 600,-1650 + 600,-1650 + 650,-1600 + 650,-1600 + + 600,-1600 + 650,- 500 + 600,-1650 + 600,-1650 + + 650,- 450 + 600,- 550 + 650,- 450 + 600,- 550 + + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500 + + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,- 500 + 650 -Duration=67800us +Duration=67900us Send NEC with 16 bit address -Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=765000us, Duration=67800us +Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=765500us, Duration=67850us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -765000 +rawIRTimings[68]: + -765500 +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,- 550 + 700,-1550 + 650,- 450 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 650,-1600 + + 600,-1650 + 650,- 500 + 600,-1650 + 650,-1600 + + 600,- 500 + 600,- 550 + 600,- 500 + 650,- 500 + + 600,-1650 + 650,-1550 + 650,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,- 500 + 600,- 500 + 650,- 500 + 600,-1600 - + 650,-1600 + 650,-1600 + 650,-1600 + 600,- 500 - + 650 -Duration=67800us + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 650,-1600 + 650,- 500 + + 600 +Duration=67850us Send NEC2 with 16 bit address -Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=764400us, Duration=67800us +Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=745150us, Duration=67900us Send with: IrSender.sendNEC(0xF2, 0x87, ); -rawData[68]: - -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 +rawIRTimings[68]: + -745150 + +8900,-4450 + + 600,- 500 + 650,-1600 + 600,- 550 + 600,- 500 + + 650,-1600 + 650,-1600 + 650,-1600 + 600,-1600 + + 650,-1600 + 650,- 500 + 600,-1650 + 600,-1650 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 650,-1600 + 600,-1650 + 600,-1650 + 650,- 450 + + 600,- 550 + 650,- 500 + 600,- 500 + 600,-1650 + + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 + + 600,-1650 + 650,-1550 + 600,-1650 + 650,- 500 + 600 -Duration=67800us +Duration=67900us Send Onkyo (NEC with 16 bit command) -Protocol=Onkyo Address=0xF2, Command=0x8887, Raw-Data=0x888700F2, 32 bits, LSB first, Gap=765000us, Duration=62300us +Protocol=Onkyo Address=0xF2, Command=0x8887, Raw-Data=0x888700F2, 32 bits, LSB first, Gap=745700us, Duration=62350us Send with: IrSender.sendOnkyo(0xF2, 0x8887, ); -rawData[68]: - -765000 - +8950,-4350 - + 650,- 500 + 650,-1600 + 600,- 500 + 650,- 500 +rawIRTimings[68]: + -745700 + +8950,-4400 + + 650,- 500 + 600,-1650 + 650,- 450 + 600,- 550 + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 - + 650,- 500 + 600,- 500 + 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 + + 650,- 500 + 600,- 500 + 600,- 550 + 650,- 500 + + 600,- 500 + 600,- 550 + 650,- 500 + 600,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500 + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650 -Duration=62300us + + 650,- 500 + 600,- 500 + 650,- 500 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1650 + + 600 +Duration=62350us Send Apple -Protocol=Apple Address=0xF2, Command=0x87, Raw-Data=0xF28787EE, 32 bits, LSB first, Gap=763450us, Duration=71150us +Protocol=Apple Address=0xF2, Command=0x87, Raw-Data=0xF28787EE, 32 bits, LSB first, Gap=744200us, Duration=71250us Send with: IrSender.sendApple(0xF2, 0x87, ); -rawData[68]: - -763450 +rawIRTimings[68]: + -744200 +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 + + 600,- 550 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,-1650 + 600,-1600 + 650,-1600 + 600,- 550 + + 600,- 500 + 600,- 550 + 650,- 500 + 600,-1600 + + 650,-1600 + 600,-1650 + 650,-1600 + 650,- 450 + + 600,- 550 + 600,- 550 + 600,- 500 + 700,-1550 + + 600,- 550 + 650,-1600 + 650,- 450 + 650,- 500 + + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650 + + 650 +Duration=71250us Send Panasonic -Protocol=Panasonic Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=763500us, Duration=59350us +Protocol=Panasonic Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=744250us, Duration=60100us Send with: IrSender.sendPanasonic(0xF2, 0x87, ); -rawData[100]: - -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 -Duration=59350us +rawIRTimings[100]: + -744250 + +3400,-1750 + + 500,- 400 + 450,-1300 + 500,- 400 + 450,- 400 + + 450,- 450 + 500,- 400 + 500,- 400 + 500,- 350 + + 450,- 450 + 500,- 400 + 500,- 350 + 550,- 350 + + 500,- 400 + 500,-1250 + 450,- 400 + 500,- 400 + + 500,- 400 + 500,- 400 + 450,- 400 + 500,- 400 + + 500,- 400 + 450,-1250 + 550,- 350 + 550,- 350 + + 500,-1250 + 500,-1250 + 450,-1250 + 500,-1250 + + 500,- 400 + 500,- 400 + 500,- 350 + 450,- 450 + + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 400 + + 450,- 400 + 550,- 350 + 500,- 400 + 450,-1250 + + 550,- 350 + 500,- 400 + 500,- 350 + 500,-1250 + + 450,- 450 + 500,-1250 + 500,- 400 + 450,-1300 + + 400 +Duration=60100us -Send Kaseikyo with 0x4711 as Vendor ID -Protocol=Kaseikyo Address=0xF2, Command=0x87, Extra=0x4711, Raw-Data=0xAB870F23, 48 bits, LSB first, Gap=783250us, Duration=66150us +Send Kaseikyo with extra=0x4711 as Vendor ID +Protocol=Kaseikyo Address=0xF2, Command=0x87, Extra=0x4711, Raw-Data=0xAB870F23, 48 bits, LSB first, Gap=764450us, Duration=67100us Send with: IrSender.sendKaseikyo(0xF2, 0x87, , 0x4711); -rawData[100]: - -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 -Duration=66150us +rawIRTimings[100]: + -764450 + +3500,-1700 + + 500,-1250 + 500,- 400 + 400,- 450 + 550,- 350 + + 500,-1250 + 500,- 400 + 450,- 450 + 450,- 400 + + 500,-1250 + 500,-1250 + 450,-1300 + 500,- 400 + + 500,- 400 + 450,- 400 + 500,-1250 + 500,- 350 + + 500,-1250 + 550,-1200 + 500,- 400 + 500,- 350 + + 500,- 400 + 500,-1250 + 500,- 400 + 400,- 500 + + 450,-1250 + 500,-1250 + 500,-1250 + 500,-1250 + + 500,- 400 + 500,- 350 + 500,- 400 + 500,- 400 + + 500,-1250 + 500,-1250 + 500,-1250 + 500,- 350 + + 500,- 400 + 500,- 400 + 500,- 350 + 550,-1200 + + 500,-1250 + 500,-1250 + 500,- 400 + 450,-1250 + + 550,- 350 + 500,-1250 + 500,- 400 + 450,-1300 + + 500 +Duration=67100us Send Kaseikyo_Denon variant -Protocol=Kaseikyo_Denon Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=784050us, Duration=62700us +Protocol=Kaseikyo_Denon Address=0xF2, Command=0x87, Raw-Data=0xA8870F20, 48 bits, LSB first, Gap=764750us, Duration=63650us Send with: IrSender.sendKaseikyo_Denon(0xF2, 0x87, ); -rawData[100]: - -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,- 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 -Duration=62700us - - -Send Denon with repeats -Protocol=Denon Address=0x12, Command=0x87, Raw-Data=0x10F2, 15 bits, LSB first, Gap=782850us, Duration=22100us +rawIRTimings[100]: + -764750 + +3550,-1650 + + 500,- 400 + 500,- 400 + 500,-1200 + 550,- 350 + + 450,-1300 + 450,- 400 + 550,-1200 + 450,- 450 + + 500,- 400 + 400,-1300 + 550,- 350 + 500,- 400 + + 450,-1300 + 500,-1250 + 450,- 400 + 500,- 400 + + 500,- 400 + 500,- 400 + 400,- 450 + 500,- 400 + + 450,- 450 + 400,-1300 + 500,- 450 + 450,- 400 + + 500,-1250 + 500,-1250 + 500,-1250 + 500,-1200 + + 500,- 400 + 450,- 450 + 500,- 400 + 500,- 350 + + 500,-1250 + 450,-1300 + 500,-1250 + 500,- 400 + + 450,- 400 + 500,- 400 + 500,- 400 + 500,-1250 + + 400,- 500 + 450,- 400 + 500,- 400 + 500,-1250 + + 500,- 350 + 450,-1300 + 500,- 400 + 500,-1250 + + 500 +Duration=63650us + + +Send Denon with 2 autorepeats after 45 ms +Protocol=Denon Address=0x12, Command=0x87, Raw-Data=0x10F2, 15 bits, LSB first, Gap=765050us, Duration=22400us Send with: IrSender.sendDenon(0x12, 0x87, ); -rawData[32]: - -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 -Duration=22100us +rawIRTimings[32]: + -765050 + + 350,- 700 + 350,-1750 + 350,- 700 + 350,- 700 + + 350,-1750 + 350,-1750 + 350,-1750 + 350,-1700 + + 300,- 800 + 300,- 750 + 300,- 750 + 300,- 750 + + 300,-1750 + 350,- 750 + 300,- 750 + 350 +Duration=22400us -Send Denon/Sharp variant with repeats -Protocol=Sharp Address=0x12, Command=0x87, Raw-Data=0x30F2, 15 bits, LSB first, Gap=726100us, Duration=23150us +Send Denon/Sharp variant with 2 autorepeat5 after 45 ms +Protocol=Sharp Address=0x12, Command=0x87, Raw-Data=0x30F2, 15 bits, LSB first, Gap=728100us, Duration=23400us Send with: IrSender.sendSharp(0x12, 0x87, ); -rawData[32]: - -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 +rawIRTimings[32]: + -728100 + + 350,- 700 + 300,-1800 + 350,- 700 + 300,- 750 + + 350,-1750 + 300,-1800 + 300,-1750 + 350,-1750 + + 350,- 700 + 350,- 750 + 300,- 750 + 300,- 750 + + 300,-1800 + 300,-1750 + 350,- 700 + 350 +Duration=23400us Send Sony/SIRCS with 7 command and 5 address bits -Protocol=Sony Address=0x12, Command=0x7, Raw-Data=0x907, 12 bits, LSB first, Gap=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 +Protocol=Sony Address=0x12, Command=0x7, Raw-Data=0x907, 12 bits, LSB first, Gap=727550us, Duration=20000us +Send with: IrSender.sendSony(0x12, 0x7, , 12); +rawIRTimings[26]: + -727550 + +2450,- 550 + +1300,- 500 +1250,- 600 +1250,- 550 + 650,- 550 + + 650,- 550 + 700,- 550 + 650,- 550 + 650,- 550 + +1250,- 600 + 700,- 500 + 700,- 500 +1250 +Duration=20000us Send Sony/SIRCS with 7 command and 8 address bits -Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 15 bits, LSB first, Gap=743050us, Duration=25250us -Send with: IrSender.sendSony(0xF2, 0x7, 2, 15); -rawData[32]: - -743050 +Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 15 bits, LSB first, Gap=725050us, Duration=25400us +Send with: IrSender.sendSony(0xF2, 0x7, , 15); +rawIRTimings[32]: + -725050 +2450,- 550 - +1300,- 500 +1250,- 550 +1250,- 550 + 650,- 550 - + 650,- 550 + 650,- 550 + 650,- 550 + 650,- 550 - +1250,- 550 + 650,- 550 + 600,- 600 +1250,- 550 + +1300,- 500 +1250,- 550 +1300,- 500 + 700,- 550 + + 700,- 500 + 700,- 500 + 700,- 550 + 700,- 500 + +1250,- 550 + 650,- 550 + 650,- 600 +1300,- 500 +1250,- 550 +1250,- 550 +1250 -Duration=25250us +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=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 Sony/SIRCS with 7 command and 13 address bits and no repeats +Protocol=Sony Address=0xF2, Command=0x7, Raw-Data=0x7907, 20 bits, LSB first, Gap=729700us, Duration=31500us +Send with: IrSender.sendSony(0xF2, 0x7, , 20); +rawIRTimings[42]: + -729700 + +2400,- 600 + +1250,- 550 +1300,- 500 +1250,- 550 + 700,- 550 + + 650,- 550 + 700,- 500 + 700,- 550 + 650,- 550 + +1300,- 500 + 650,- 550 + 700,- 550 +1250,- 550 + +1250,- 550 +1300,- 500 +1250,- 550 + 650,- 600 + + 650,- 550 + 650,- 550 + 700,- 550 + 650 +Duration=31500us Send Samsung 8 bit command and 8 bit address -Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x7887F2F2, 32 bits, LSB first, Gap=751200us, Duration=65550us +Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x7887F2F2, 32 bits, LSB first, Gap=752900us, Duration=65650us 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 +rawIRTimings[68]: + -752900 + +4500,-4450 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,-1600 + + 650,- 500 + 650,-1600 + 650,- 450 + 650,- 500 + + 600,-1650 + 650,-1550 + 650,-1600 + 600,-1650 + + 600,-1650 + 650,-1600 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 550 + 650,-1550 + + 650,- 500 + 600,- 550 + 650,- 450 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,-1650 + 600,- 500 + 600 -Duration=65550us +Duration=65650us + + +Send Samsung 8 bit command and 16 bit address +Protocol=Samsung Address=0xF2, Command=0x87, Raw-Data=0x788700F2, 32 bits, LSB first, Gap=747150us, Duration=60150us +Send with: IrSender.sendSamsung(0xF2, 0x87, ); +rawIRTimings[68]: + -747150 + +4500,-4400 + + 650,- 500 + 650,-1600 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 + + 600,- 550 + 600,- 500 + 600,- 550 + 650,- 500 + + 600,- 500 + 650,- 500 + 600,- 500 + 700,- 450 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 + + 650 +Duration=60150us Send Samsung 16 bit command and address -Protocol=Samsung Address=0xF2, Command=0xA987, Raw-Data=0xA98700F2, 32 bits, LSB first, Gap=766150us, Duration=60050us +Protocol=Samsung Address=0xF2, Command=0xA987, Raw-Data=0xA98700F2, 32 bits, LSB first, Gap=746700us, Duration=60200us 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 +rawIRTimings[68]: + -746700 + +4450,-4450 + + 650,- 500 + 600,-1650 + 600,- 500 + 600,- 550 + + 650,-1600 + 600,-1650 + 600,-1600 + 600,-1650 + + 600,- 550 + 650,- 500 + 600,- 500 + 600,- 550 + + 600,- 550 + 600,- 500 + 700,- 450 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 600,- 500 + + 600,- 550 + 600,- 550 + 600,- 500 + 600,-1650 + + 650,-1600 + 650,- 500 + 650,- 500 + 600,-1600 + + 600,- 550 + 600,-1650 + 600,- 500 + 650,-1600 + + 650 +Duration=60200us Send Samsung48 16 bit command -Protocol=Samsung48 Address=0xF2, Command=0xA987, Raw-Data=0x56A9, 48 bits, LSB first, Gap=765650us, Duration=87000us +Protocol=Samsung48 Address=0xF2, Command=0xA987, Raw-Data=0x56A9, 48 bits, LSB first, Gap=746150us, Duration=87100us 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 +rawIRTimings[100]: + -746150 + +4550,-4350 + + 650,- 500 + 650,-1600 + 600,- 550 + 600,- 500 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,- 500 + + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 550 + + 650,-1550 + 650,-1600 + 650,-1600 + 650,- 500 + + 600,- 500 + 650,- 500 + 650,- 500 + 600,-1600 + + 600,- 550 + 650,- 500 + 600,- 500 + 650,-1600 + + 650,-1600 + 600,-1600 + 600,-1650 + 650,- 500 + 600,-1650 + 600,- 550 + 600,- 500 + 650,-1600 - + 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 + + 650,- 500 + 600,-1650 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,-1600 + 650,-1600 + 600,- 550 + + 600,-1650 + 600,- 500 + 650,-1600 + 650,- 500 + + 600 +Duration=87100us Send RC5 -Protocol=RC5 Address=0x12, Command=0x7, Raw-Data=0x1487, 13 bits, MSB first, Gap=781750us, Duration=24000us +Protocol=RC5 Address=0x12, Command=0x7, Toggle=1, Raw-Data=0x1C87, 13 bits, MSB first, Gap=762250us, Duration=24200us Send with: IrSender.sendRC5(0x12, 0x7, ); -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 +rawIRTimings[24]: + -762250 + + 950,- 850 + + 950,- 800 +1000,- 850 +1850,- 800 + 950,-1750 + +1800,- 850 + 950,- 850 + 950,- 800 +1000,-1700 + + 900,- 850 +1000,- 800 +1000 +Duration=24200us Send RC5X with 7.th MSB of command set -Protocol=RC5 Address=0x12, Command=0x47, Toggle=1, Raw-Data=0xC87, 13 bits, MSB first, Gap=742250us, Duration=24050us +Protocol=RC5 Address=0x12, Command=0x47, Raw-Data=0x487, 13 bits, MSB first, Gap=724200us, Duration=24150us 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 +rawIRTimings[22]: + -724200 + +1850,- 800 + + 950,-1750 +1800,- 850 + 950,-1750 +1850,- 800 + + 950,- 800 +1000,- 800 + 950,-1750 + 950,- 800 + +1000,- 800 +1000 +Duration=24150us + + +Send Marantz with RC5 and extra=0x38 +Protocol=Marantz Address=0x12, Command=0x7, Extra=0x38, Toggle=1, Raw-Data=0x721F8, 19 bits, MSB first, Gap=722250us, Duration=37500us +Send with: IrSender.sendMarantz(0x12, 0x7, , 0x38); +rawIRTimings[34]: + -722250 + + 950,- 850 + + 950,- 850 + 900,- 850 +1900,- 800 + 900,-1800 + +1800,-4350 +1000,- 800 + 950,- 850 + 950,-1750 + + 900,- 850 +1000,- 750 +1000,- 850 + 950,- 850 + + 900,- 850 +1850,- 800 +1000,- 850 + 900 +Duration=37500us + + +Send Marantz with RC5A and extra=0x38 +Protocol=Marantz Address=0x12, Command=0x47, Extra=0x38, Raw-Data=0x121F8, 19 bits, MSB first, Gap=732750us, Duration=37550us +Send with: IrSender.sendMarantz(0x12, 0x47, , 0x38); +rawIRTimings[32]: + -732750 + +1850,- 800 + + 950,-1700 +1850,- 850 + 900,-1800 +1800,-4400 + +1000,- 800 + 950,- 800 +1000,-1700 + 950,- 850 + + 950,- 850 + 900,- 900 + 950,- 800 + 950,- 850 + +1850,- 850 + 900,- 850 +1000 +Duration=37550us Send RC6 -Protocol=RC6 Address=0xF2, Command=0x87, Toggle=1, Raw-Data=0x1F287, 20 bits, MSB first, Gap=739800us, Duration=22850us +Protocol=RC6 Address=0xF2, Command=0x87, Toggle=1, Raw-Data=0x1F287, 20 bits, MSB first, Gap=727650us, Duration=23200us Send with: IrSender.sendRC6(0xF2, 0x87, ); -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 +rawIRTimings[36]: + -727650 + +2750,- 750 + + 550,- 800 + 600,- 350 + 550,- 400 +1400,- 850 + + 500,- 400 + 550,- 350 + 550,- 350 + 550,- 850 + + 550,- 350 +1000,- 850 + 950,- 850 + 550,- 350 + + 500,- 400 + 550,- 350 +1000,- 400 + 550,- 350 + + 550 +Duration=23200us -Send RC6A with 14 bit 0x2711 as extra -Protocol=RC6A Address=0xF2, Command=0x87, Extra=0x2711, Raw-Data=0x2711F287, 35 bits, MSB first, Gap=751050us, Duration=36400us +Send RC6A with 14 bit and extra=0x2711 +Protocol=RC6A Address=0xF2, Command=0x87, Extra=0x2711, Raw-Data=0x2711F287, 35 bits, MSB first, Gap=730650us, Duration=37000us Send with: IrSender.sendRC6A(0xF2, 0x87, , 0x2711); -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 +rawIRTimings[60]: + -730650 + +2750,- 800 + + 500,- 400 + 500,- 400 + 550,- 850 + 500,- 850 + + 950,- 400 +1000,- 850 + 500,- 400 +1000,- 400 + + 500,- 450 + 450,- 850 + 500,- 450 + 500,- 400 + + 950,- 900 + 500,- 400 + 500,- 400 +1050,- 350 + + 500,- 400 + 500,- 400 + 500,- 450 + 500,- 800 + + 600,- 350 +1000,- 850 +1000,- 800 + 550,- 400 + + 500,- 450 + 500,- 400 +1000,- 400 + 550,- 350 + + 500 +Duration=37000us Send MagiQuest, WandId=0x6BCD00F2 -Protocol=MagiQuest Address=0xF2, Command=0x187, Raw-Data=0x6BCD00F2, 56 bits, MSB first, Gap=765950us, Duration=63700us +Protocol=MagiQuest Address=0xF2, Command=0x187, Raw-Data=0x6BCD00F2, 56 bits, MSB first, Gap=744850us, Duration=64800us 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 OpenLASIR mode fire and color orange -Protocol=Onkyo Address=0xF2, Command=0x6087, Raw-Data=0x60870DF2, 32 bits, LSB first, Gap=791650us, Duration=65650us -Send with: IrSender.sendOnkyo(0xF2, 0x6087, ); -rawIRTimings[68]: - -791650 - +8950,-4400 - + 650,- 450 + 650,-1600 + 650,- 500 + 650,- 450 - + 650,-1600 + 650,-1600 + 600,-1650 + 650,-1600 - + 600,-1600 + 600,- 550 + 600,-1650 + 600,-1600 - + 650,- 500 + 600,- 550 + 600,- 500 + 650,- 500 - + 650,-1600 + 650,-1600 + 650,-1550 + 650,- 500 - + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600 - + 650,- 450 + 650,- 500 + 650,- 500 + 600,- 500 - + 600,- 550 + 650,-1600 + 600,-1600 + 650,- 500 +rawIRTimings[112]: + -744850 + + 400,- 750 + 400,- 800 + 350,- 800 + 400,- 800 + + 350,- 800 + 400,- 800 + 350,- 800 + 350,- 850 + + 650,- 550 + 600,- 550 + 350,- 800 + 600,- 600 + + 350,- 800 + 600,- 550 + 650,- 550 + 650,- 500 + + 650,- 500 + 400,- 800 + 350,- 800 + 650,- 550 + + 600,- 550 + 350,- 800 + 650,- 550 + 350,- 800 + + 400,- 800 + 350,- 800 + 400,- 800 + 350,- 800 + + 350,- 800 + 400,- 800 + 400,- 750 + 650,- 550 + + 600,- 550 + 650,- 500 + 700,- 500 + 350,- 800 + + 400,- 750 + 650,- 550 + 350,- 850 + 600,- 550 + + 650,- 550 + 350,- 800 + 350,- 800 + 350,- 850 + + 350,- 800 + 650,- 500 + 650,- 550 + 650,- 550 + + 400,- 750 + 400,- 800 + 600,- 550 + 350,- 800 + + 400,- 800 + 350,- 800 + 650,- 500 + 400 +Duration=64800us + + +Send OpenLASIR mode fire and color orange, detected as ONKYO +Protocol=Onkyo Address=0xF2, Command=0xC087, Raw-Data=0xC0870DF2, 32 bits, LSB first, Gap=793250us, Duration=65650us +Send with: IrSender.sendOnkyo(0xF2, 0xC087, ); +rawIRTimings[68]: + -793250 + +8900,-4450 + + 600,- 500 + 650,-1600 + 650,- 500 + 600,- 500 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,-1600 + + 650,-1600 + 650,- 450 + 600,-1650 + 650,-1600 + + 650,- 500 + 600,- 500 + 600,- 550 + 600,- 500 + + 650,-1600 + 650,-1600 + 600,-1650 + 650,- 450 + + 650,- 500 + 700,- 450 + 600,- 500 + 650,-1600 + + 650,- 500 + 600,- 500 + 650,- 500 + 650,- 500 + + 600,- 500 + 600,- 550 + 600,-1650 + 600,-1650 + 600 Duration=65650us Send Lego with 2 channel and with 4 command bits -Protocol=Lego Address=0x2, Command=0x17, Raw-Data=0x217B, 16 bits, MSB first, Gap=791750us, Duration=10550us +Protocol=Lego Address=0x2, Command=0x17, Raw-Data=0x217B, 16 bits, MSB first, Gap=747400us, Duration=10850us 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 +rawIRTimings[36]: + -747400 + + 250,- 950 + + 200,- 550 + 250,- 500 + 200,- 150 + 300,- 500 + + 200,- 500 + 250,- 500 + 250,- 500 + 250,- 200 + + 200,- 500 + 250,- 150 + 300,- 150 + 250,- 250 + + 200,- 250 + 250,- 450 + 250,- 200 + 250,- 150 + + 300 +Duration=10850us + + +Send 16 bit Bang&Olufsen / 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 +rawIRTimings[86]: + -749450 + + 250,-2850 + + 300,-2800 + 300,-12750 + 300,-2850 + 250,-9050 + + 300,-5900 + 300,-5900 + 250,-5950 + 300,-2850 + + 250,-5950 + 250,-9050 + 250,-2850 + 300,-9000 + + 300,-2800 + 250,-6000 + 250,-5950 + 300,-5900 + + 300,-9000 + 300,-5950 + 250,-5950 + 300,-12100 + + 300,-2850 + 300,-2800 + 250,-12750 + 250,-2850 + + 300,-9000 + 300,-5900 + 300,-5950 + 250,-5950 + + 250,-2850 + 300,-5900 + 300,-9000 + 300,-2850 + + 250,-9050 + 250,-2850 + 300,-5950 + 250,-5950 + + 250,-5950 + 300,-9000 + 300,-5900 + 250,-6000 + + 250,-12150 + 250 +Duration=274750us - Now try to decode the first 6 entries, which results in rawData 0x0 -Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=748450us, Duration=6400us +Protocol=Bang&Olufsen Address=0x0, Command=0x0, Raw-Data=0x0, 0 bits, MSB first, Gap=749450us, Duration=6500us - Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode -Protocol=Bang&Olufsen Address=0xF2, Command=0x87, Raw-Data=0xF287, 16 bits, MSB first, Gap=12750us, Duration=118050us +Protocol=Bang&Olufsen Address=0xF2, Command=0x87, Raw-Data=0xF287, 16 bits, MSB first, Gap=12750us, Duration=255500us Send with: IrSender.sendBang&Olufsen(0xF2, 0x87, ); -rawData[38]: +rawIRTimings[80]: -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 + + 300,-2850 + + 250,-9050 + 300,-5900 + 300,-5900 + 250,-5950 + + 300,-2850 + 250,-5950 + 250,-9050 + 250,-2850 + + 300,-9000 + 300,-2800 + 250,-6000 + 250,-5950 + + 300,-5900 + 300,-9000 + 300,-5950 + 250,-5950 + + 300,-12100 + 300,-2850 + 300,-2800 + 250,-12750 + + 250,-2850 + 300,-9000 + 300,-5900 + 300,-5950 + + 250,-5950 + 250,-2850 + 300,-5900 + 300,-9000 + + 300,-2850 + 250,-9050 + 250,-2850 + 300,-5950 + + 250,-5950 + 250,-5950 + 300,-9000 + 300,-5900 + + 250,-6000 + 250,-12150 + 250 +Duration=255500us Send next protocols with IrSender.write Send JVC -Protocol=JVC Address=0xF2, Command=0x87, Raw-Data=0x87F2, 16 bits, LSB first, Gap=804750us, Duration=39400us +Protocol=JVC Address=0xF2, Command=0x87, Raw-Data=0x87F2, 16 bits, LSB first, Gap=850000us, Duration=39600us Send with: IrSender.sendJVC(0xF2, 0x87, ); -rawData[36]: - -804750 +rawIRTimings[36]: + -850000 +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 + + 650,- 400 + 600,-1500 + 650,- 450 + 600,- 500 + + 550,-1500 + 550,-1600 + 600,-1500 + 550,-1550 + + 600,-1500 + 600,-1500 + 600,-1550 + 550,- 500 + + 600,- 450 + 550,- 550 + 550,- 500 + 600,-1500 + 600 -Duration=39400us +Duration=39600us Send LG -Protocol=LG Address=0xF2, Command=0xA987, Raw-Data=0xF2A9872, 28 bits, MSB first, Gap=745550us, Duration=57400us +Protocol=LG Address=0xF2, Command=0xA987, Raw-Data=0xF2A9872, 28 bits, MSB first, Gap=726100us, Duration=57800us 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 +rawIRTimings[60]: + -726100 + +8950,-4150 + + 550,-1550 + 550,-1500 + 600,-1500 + 600,-1500 + + 550,- 500 + 650,- 450 + 550,-1500 + 550,- 500 + + 600,-1500 + 550,- 500 + 550,-1550 + 600,- 450 + + 600,-1500 + 600,- 450 + 600,- 450 + 600,-1500 + + 600,-1500 + 550,- 500 + 600,- 450 + 600,- 500 + + 550,- 500 + 600,-1500 + 550,-1500 + 600,-1500 + + 600,- 450 + 550,- 550 + 550,-1500 + 600,- 500 + + 600 +Duration=57800us Send Bosewave with no address and 8 command bits -Protocol=BoseWave Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=762100us, Duration=26750us +Protocol=BoseWave Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=762350us, Duration=27150us 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 +rawIRTimings[36]: + -762350 + +1100,-1400 + + 600,-1400 + 600,-1400 + 600,-1400 + 600,- 400 + + 600,- 450 + 600,- 400 + 550,- 450 + 550,-1450 + + 550,- 450 + 600,- 400 + 600,- 400 + 550,-1450 + + 600,-1400 + 600,-1400 + 550,-1450 + 600,- 450 + 550 -Duration=26750us +Duration=27150us Send FAST -Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=746450us, Duration=28950us +Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=726950us, Duration=29200us 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 +rawIRTimings[36]: + -726950 + +2200,-1000 + + 600,-1500 + 600,-1500 + 550,-1550 + 600,- 500 + + 600,- 500 + 550,- 500 + 550,- 500 + 600,-1500 + + 600,- 450 + 600,- 500 + 550,- 500 + 600,-1500 + + 600,-1550 + 600,-1500 + 550,-1550 + 600,- 500 + 550 -Duration=28950us +Duration=29200us 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 +rawIRTimings[400]: + -725800 + + 300,- 450 + + 300,- 500 + 200,- 550 + 300,- 450 + 250,- 550 + + 300,- 450 + 300,- 450 + 300,- 500 + 250,- 500 + + 200,- 550 + 300,- 500 + 200,- 550 + 300,- 500 + + 250,- 500 + 200,- 600 + 250,- 500 + 250,- 500 + + 200,- 550 + 250,- 550 + 250,- 500 + 250,- 500 + + 200,- 550 + 300,- 500 + 200,- 550 + 250,- 500 + + 300,- 500 + 200,- 550 + 200,- 550 + 300,- 450 + + 300,- 500 + 200,- 550 + 200,- 550 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500 + + 300,- 450 + 300,- 500 + 300,- 450 + 250,- 500 + + 300,- 500 + 250,- 500 + 300,- 450 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500 + + 300,- 450 + 300,- 500 + 250,- 500 + 300,- 450 + + 300,- 500 + 250,- 500 + 250,- 500 + 300,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500 + + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500 + + 300,- 500 + 250,- 500 + 200,- 550 + 300,- 500 + + 200,- 550 + 250,- 500 + 250,- 550 + 250,- 500 + + 250,- 500 + 250,- 500 + 300,- 500 + 200,- 550 + + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500 - + 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 - + + 250,- 500 + 250,- 550 + 250,- 500 + 250,- 550 + + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 500 + + 250,- 500 + 300,- 500 + 250,- 500 + 250,- 500 + + 250,- 500 + 300,- 500 + 250,- 500 + 300,- 500 + + 200,- 550 + 250,- 500 + 300,- 500 + 250,- 500 + + 300,- 450 + 200,- 600 + 250,- 500 + 300,- 450 + + 250,- 500 + 250,- 550 + 300,- 450 + 250,- 500 + + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 550 + + 250,- 500 + 300,- 450 + 250,- 550 + 300,- 450 + + 200,- 550 + 300,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500 + + 300,- 500 + 300,- 450 + 250,- 500 + 250,- 500 + + 300,- 500 + 250,- 500 + 250,- 550 + 250,- 500 + + 250,- 500 + 300,- 450 + 300,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 200,- 550 + + 300,- 500 + 250,- 500 + 250,- 550 + 250,- 500 + + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 500 + 250,- 550 + 200,- 550 + + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 500 + 250,- 550 + 250,- 500 + + 250,- 550 + 200,- 550 + 250,- 500 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500 + + 250,- 550 + 250,- 500 + 250,- 500 + 250,- 550 + + 250,- 500 + 250,- 550 + 200,- 600 + 200,- 500 + + 250,- 500 + 250,- 550 + 200,- 550 + 250,- 500 + + 250,- 600 + 200,- 550 + 200 +Duration=152850us + +Invert toggle value for next loop Stop receiver Start receiver address=0x1F3 command=0x98 repeats=2 Send NEC with 8 bit address and complete NEC frames as repeats to force decoding as NEC2 -Protocol=NEC Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Gap=923500us, Duration=67850us +Protocol=NEC Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Gap=915450us, 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 +rawIRTimings[68]: + -915450 + +8900,-4450 + + 600,-1600 + 650,-1600 + 600,- 550 + 600,- 500 + + 700,-1550 + 600,-1650 + 650,-1600 + 600,-1600 + + 600,- 550 + 600,- 550 + 650,-1600 + 600,-1600 + + 650,- 500 + 650,- 500 + 600,- 500 + 600,- 550 + 600,- 500 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 - + 650,-1600 + 650,-1600 + 600,-1600 + 650,- 500 - + 650,- 500 + 600,-1600 + 600,-1650 + 600,- 550 + + 650,-1600 + 650,- 500 + 650,- 450 + 600,-1650 + + 600,-1650 + 600,-1650 + 600,-1600 + 650,- 500 + + 650,- 450 + 650,-1600 + 650,-1600 + 600,- 550 + 600 Duration=67850us -Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=68750us, Duration=67850us +Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69250us, Duration=67900us Send with: IrSender.sendNEC2(0xF3, 0x98, ); -rawData[68]: - -68750 - +8950,-4350 +rawIRTimings[68]: + -69250 + +8900,-4400 + 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,-1600 + 650,-1600 + 600,-1650 + 600,-1650 + + 600,- 500 + 650,- 500 + 650,-1600 + 600,-1650 + + 600,- 500 + 650,- 500 + 600,- 550 + 600,- 500 + + 600,- 550 + 600,- 500 + 650,- 500 + 650,-1600 + + 600,-1600 + 650,- 500 + 650,- 500 + 600,-1600 + + 650,-1600 + 600,-1650 + 650,-1600 + 600,- 500 + + 600,- 550 + 600,-1650 + 600,-1600 + 650,- 500 + 650 -Duration=67850us +Duration=67900us -Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69400us, Duration=67850us +Protocol=NEC2 Address=0xF3, Command=0x98, Raw-Data=0x67980CF3, 32 bits, LSB first, Repeat, Gap=69850us, Duration=67900us 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 +rawIRTimings[68]: + -69850 +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 + + 650,-1600 + 600,-1650 + 600,- 500 + 600,- 550 + + 600,-1650 + 600,-1600 + 650,-1600 + 650,-1600 + + 600,- 550 + 600,- 500 + 650,-1600 + 650,-1600 + + 650,- 450 + 650,- 500 + 650,- 500 + 650,- 450 + + 600,- 550 + 650,- 450 + 650,- 500 + 650,-1600 + + 600,-1650 + 600,- 500 + 650,- 500 + 600,-1650 + + 650,-1550 + 650,-1600 + 650,-1600 + 650,- 500 + 600,- 500 + 650,-1600 + 650,-1600 + 650,- 450 + 650 -Duration=66750us - - +Duration=67900us diff --git a/src/IRCommandDispatcher.h b/src/IRCommandDispatcher.h index 83a98b27c..74b362c63 100644 --- a/src/IRCommandDispatcher.h +++ b/src/IRCommandDispatcher.h @@ -5,7 +5,7 @@ * * To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" * - * Copyright (C) 2019-2024 Armin Joachimsmeyer + * Copyright (C) 2019-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. @@ -31,6 +31,13 @@ #include +//#define DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT // Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry. +//#define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries. +#if defined(USE_DISPATCHER_COMMAND_STRINGS) +#define COMMAND_STRING(anyString) anyString +#else +#define COMMAND_STRING(anyString) +#endif /* * For command mapping file */ @@ -41,7 +48,6 @@ #define IR_COMMAND_FLAG_BEEP 0x04 // Do a single short beep before executing command. May not be useful for short or repeating commands. #define IR_COMMAND_FLAG_BLOCKING_BEEP (IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP) - #if !defined(IS_STOP_REQUESTED) #define IS_STOP_REQUESTED IRDispatcher.requestToStopReceived #endif @@ -55,39 +61,35 @@ #define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return #endif -// Basic mapping structure -struct IRToCommandMappingStruct { -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) - uint16_t IRCode; +/* + * Define as COMMAND_EMPTY a code which is not sent by the remote - otherwise please redefine it here + */ +#if defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT) +#define COMMAND_EMPTY __UINT_FAST16_MAX__ // 0xFFFF code no command +typedef uint_fast16_t IRCommandType; #else - uint8_t IRCode; +typedef uint_fast8_t IRCommandType; +#define COMMAND_EMPTY __UINT_FAST8_MAX__ // 0xFF code no command #endif + +// Basic mapping structure +struct IRToCommandMappingStruct { + IRCommandType IRCode; uint8_t Flags; void (*CommandToCall)(); +#if defined(USE_DISPATCHER_COMMAND_STRINGS) const char *CommandString; +#endif }; struct IRDataForCommandDispatcherStruct { uint16_t address; // to distinguish between multiple senders -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) - uint16_t command; -#else - uint8_t command; -#endif + IRCommandType command; bool isRepeat; - uint32_t MillisOfLastCode; // millis() of last IR command -including repeats!- received - for timeouts etc. - volatile bool isAvailable; // flag for a polling interpreting function, that a new command has arrived. Is set true by library and set false by main loop. + volatile uint32_t MillisOfLastCode; // millis() of last IR command -including repeats!- received - for timeouts etc. + volatile bool isAvailable; // flag for a polling interpreting function, that a new command has arrived. Is set true by library and set false by main loop. }; -/* - * Special codes (hopefully) not sent by the remote - otherwise please redefine it here - */ -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) -#define COMMAND_EMPTY 0xFFFF // code no command -#else -#define COMMAND_EMPTY 0xFF // code no command -#endif - class IRCommandDispatcher { public: void init(); @@ -95,29 +97,20 @@ class IRCommandDispatcher { bool checkAndRunNonBlockingCommands(); bool checkAndRunSuspendedBlockingCommands(); -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) - void setNextBlockingCommand(uint16_t aBlockingCommandToRunNext); -#else - void setNextBlockingCommand(uint8_t aBlockingCommandToRunNext); -#endif + void setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext); bool delayAndCheckForStop(uint16_t aDelayMillis); // The main dispatcher function void checkAndCallCommand(bool aCallBlockingCommandImmediately); void printIRCommandString(Print *aSerial); + void printIRCommandString(Print *aSerial, uint_fast8_t aMappingArrayIndex); void setRequestToStopReceived(bool aRequestToStopReceived = true); -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) - uint16_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command - uint16_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop - uint16_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop -#else - uint8_t currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command - uint8_t lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop - uint8_t BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop -#endif - bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command + IRCommandType currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command + IRCommandType lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop + IRCommandType BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop + bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command /* * Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP). * It is set if a blocking IR command received, which cannot be executed directly. Can be reset by main loop, if command has stopped. diff --git a/src/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp index 3f3971bac..bbbbd3d73 100644 --- a/src/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -36,7 +36,7 @@ * Program behavior is modified by the following macros * USE_TINY_IR_RECEIVER * USE_IRMP_LIBRARY - * IR_COMMAND_HAS_MORE_THAN_8_BIT + * DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT */ #ifndef _IR_COMMAND_DISPATCHER_HPP @@ -46,46 +46,33 @@ #include "IRCommandDispatcher.h" +//#define NO_LED_FEEDBACK_CODE // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt. + //#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding //#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding //#define USE_IRMP_LIBRARY // The IRMP library is used for decoding #if !defined(USE_TINY_IR_RECEIVER) && !defined(USE_IRREMOTE_LIBRARY) && !defined(USE_IRMP_LIBRARY) #define USE_TINY_IR_RECEIVER // Set TiniIR as default library #endif -/* - * Enable this to see information on each call. - * Since there should be no library which uses Serial, it should only be enabled for development purposes. - */ -#if defined(INFO) && !defined(LOCAL_INFO) -#define LOCAL_INFO -#else -//#define LOCAL_INFO // This enables info output only for this file -#endif -#if defined(DEBUG) -#define LOCAL_DEBUG -// Propagate debug level -#define LOCAL_INFO -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif IRCommandDispatcher IRDispatcher; -#if defined(LOCAL_INFO) -#define CD_INFO_PRINT(...) Serial.print(__VA_ARGS__); -#define CD_INFO_PRINTLN(...) Serial.println(__VA_ARGS__); -#else -#define CD_INFO_PRINT(...) void(); -#define CD_INFO_PRINTLN(...) void(); -#endif - #if defined(USE_TINY_IR_RECEIVER) /****************************** * Code for the TinyIR library ******************************/ +#if defined(USE_ONKYO_PROTOCOL) && ! defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT) +#warning ONKYO protocol has 16 bit commands so activating of DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT is recommended +#endif #define USE_CALLBACK_FOR_TINY_RECEIVER // Call the function "handleReceivedTinyIRData()" below each time a frame or repeat is received. #include "TinyIRReceiver.hpp" // included in "IRremote" and "IRMP" library +// This block must be located after the includes of other *.hpp files +//#define LOCAL_INFO // This enables info output only for this file +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" + void IRCommandDispatcher::init() { initPCIInterruptForTinyReceiver(); } @@ -110,16 +97,97 @@ void handleReceivedTinyIRData() { # endif # if defined(IR_ADDRESS) - // if available, compare address + // if available, compare address. TinyIRReceiverData.Address saves 6 bytes if (TinyIRReceiverData.Address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h - CD_INFO_PRINT(F("Wrong address. Expected 0x")); - CD_INFO_PRINTLN(IR_ADDRESS, HEX); + INFO_PRINT(F("Wrong address. Expected 0x")); + INFO_PRINTLN(IR_ADDRESS, HEX); } else # endif { IRDispatcher.IRReceivedData.isAvailable = true; // check if dispatcher enabled - if(!IRDispatcher.doNotUseDispatcher) { + if (!IRDispatcher.doNotUseDispatcher) { + /* + * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, + * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() + */ + IRDispatcher.checkAndCallCommand(false); + } + } +} + +#elif defined(USE_IRREMOTE_LIBRARY) +/********************************* + * Code for the IRremote library + *********************************/ +#define DECODE_NEC // Includes Apple and Onkyo +#include "IRremote.hpp" + +// This block must be located after the includes of other *.hpp files +//#define LOCAL_INFO // This enables info output only for this file +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" + +void ReceiveCompleteCallbackHandler(); + +void IRCommandDispatcher::init() { + // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED + IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); + /* + * Tell the ISR to call this function, when a complete frame has been received + */ + IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler); +} + +/* + * Callback function + * Here we know, that data is available. + * This function is executed in an ISR (Interrupt Service Routine) context. + * This means that interrupts are blocked here, so delay(), millis() and Serial prints of data longer than the print buffer size etc. will block forever. + * This is because they require their internal interrupt routines to run in order to return. + * Therefore it is best to make this callback function short and fast! + * A dirty hack is to enable interrupts again by calling sei() (enable interrupt again), but you should know what you are doing, + */ +#if defined(ESP32) || defined(ESP8266) +IRAM_ATTR +# endif +void ReceiveCompleteCallbackHandler() { + /* + * Fill IrReceiver.decodedIRData + */ + IrReceiver.decode(); + + IRDispatcher.IRReceivedData.address = IrReceiver.decodedIRData.address; + IRDispatcher.IRReceivedData.command = IrReceiver.decodedIRData.command; + IRDispatcher.IRReceivedData.isRepeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT; + IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); + + // Interrupts are already enabled for SUPPORT_MULTIPLE_RECEIVER_INSTANCES +#if !defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) && !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled + interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. +# endif + +# if defined(LOCAL_INFO) + IrReceiver.printIRResultMinimal(&Serial); + Serial.println(); +# endif + /* + * Enable receiving of the next frame. + */ + IrReceiver.resume(); + +# if defined(IR_ADDRESS) + // if available, compare address + if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h + INFO_PRINT(F("Wrong address. Expected 0x")); + INFO_PRINTLN(IR_ADDRESS, HEX); + } else +# endif + { + IRDispatcher.IRReceivedData.isAvailable = true; + // check if dispatcher enabled + if (!IRDispatcher.doNotUseDispatcher) { /* * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() @@ -136,6 +204,10 @@ void handleReceivedTinyIRData() { #define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used. #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings for printIRInfo() #include "irmp.hpp" +#include "LocalDebugLevelStart.h" + +IRMP_DATA irmp_data; + void handleReceivedIRData(); void IRCommandDispatcher::init() @@ -156,32 +228,26 @@ IRAM_ATTR #endif void handleReceivedIRData() { - IRMP_DATA tTeporaryData; - irmp_get_data(&tTeporaryData); - IRDispatcher.IRReceivedData.address = tTeporaryData.address; - IRDispatcher.IRReceivedData.command = tTeporaryData.command; - IRDispatcher.IRReceivedData.isRepeat = tTeporaryData.flags & IRMP_FLAG_REPETITION; + irmp_get_data(&irmp_data); + + IRDispatcher.IRReceivedData.address = irmp_data.address; + IRDispatcher.IRReceivedData.command = irmp_data.command; + IRDispatcher.IRReceivedData.isRepeat = irmp_data.flags & IRMP_FLAG_REPETITION; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled - interrupts(); // To enable delay() for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. + interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. # endif - CD_INFO_PRINT(F("A=0x")); - CD_INFO_PRINT(IRDispatcher.IRReceivedData.address, HEX); - CD_INFO_PRINT(F(" C=0x")); - CD_INFO_PRINT(IRDispatcher.IRReceivedData.command, HEX); - if (IRDispatcher.IRReceivedData.isRepeat) - { - CD_INFO_PRINT(F("R")); - } - CD_INFO_PRINTLN(); +# if defined(LOCAL_INFO) + irmp_result_print(&Serial, &irmp_data); +# endif # if defined(IR_ADDRESS) // if available, compare address if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { - CD_INFO_PRINT(F("Wrong address. Expected 0x")); - CD_INFO_PRINTLN(IR_ADDRESS, HEX); + INFO_PRINT(F("Wrong address. Expected 0x")); + INFO_PRINTLN(IR_ADDRESS, HEX); } else # endif { @@ -202,8 +268,7 @@ void handleReceivedIRData() /******************************************* * Start of the IR library independent code *******************************************/ -void IRCommandDispatcher::printIRInfo(Print *aSerial) -{ +void IRCommandDispatcher::printIRInfo(Print *aSerial) { aSerial->println(); // For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h #if defined(USE_IRMP_LIBRARY) @@ -212,9 +277,9 @@ void IRCommandDispatcher::printIRInfo(Print *aSerial) # else aSerial->println(F("Listening to IR remote at pin " STR(IRMP_INPUT_PIN))); # endif - Serial.print(F("Accepted protocols are: ")); + aSerial->print(F("Accepted protocols are: ")); irmp_print_active_protocols(&Serial); - Serial.println(); + aSerial->println(); #else # if defined(IR_REMOTE_NAME) aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IR_RECEIVE_PIN))); @@ -233,49 +298,57 @@ void IRCommandDispatcher::printIRInfo(Print *aSerial) * @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. * Should be false if called by ISR in order not to block ISR. Is true when called from checkAndRunSuspendedBlockingCommands(). */ -void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) -{ - if (IRReceivedData.command == COMMAND_EMPTY) - { +void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) { + if (IRReceivedData.command == COMMAND_EMPTY) { return; } /* * Search for command in Array of IRToCommandMappingStruct */ - for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) - { - if (IRReceivedData.command == IRMapping[i].IRCode) - { + for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { + if (IRReceivedData.command == IRMapping[i].IRCode) { /* * Command found */ #if defined(LOCAL_INFO) +# if defined(__AVR__) +# if defined(USE_DISPATCHER_COMMAND_STRINGS) const __FlashStringHelper *tCommandName = reinterpret_cast(IRMapping[i].CommandString); +# else + char tCommandName[7]; + snprintf_P(tCommandName, sizeof(tCommandName), PSTR("0x%x"), IRMapping[i].IRCode); +# endif +# else +# if defined(USE_DISPATCHER_COMMAND_STRINGS) + const char *tCommandName = IRMapping[i].CommandString; +# else + char tCommandName[7]; + snprintf(tCommandName, sizeof(tCommandName), "0x%x", IRMapping[i].IRCode); +# endif +# endif #endif /* * Check for repeat and if repeat is allowed for the current command */ - if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) - { -#if defined(LOCAL_DEBUG) - Serial.print(F("Repeats of command \"")); - Serial.print(tCommandName); - Serial.println("\" not accepted"); -#endif + if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) { + + DEBUG_PRINT(F("Repeats of command \"")); + DEBUG_PRINT(tCommandName); + DEBUG_PRINTLN("\" not accepted"); + return; } /* * Do not accept recursive call of the same command */ - if (currentBlockingCommandCalled == IRReceivedData.command) - { -#if defined(LOCAL_DEBUG) - Serial.print(F("Recursive command \"")); - Serial.print(tCommandName); - Serial.println("\" not accepted"); -#endif + if (currentBlockingCommandCalled == IRReceivedData.command) { + + DEBUG_PRINT(F("Recursive command \"")); + DEBUG_PRINT(tCommandName); + DEBUG_PRINTLN("\" not accepted"); + return; } @@ -283,11 +356,10 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate * Execute commands */ bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING); - if (tIsNonBlockingCommand) - { + if (tIsNonBlockingCommand) { // short command here, just call - CD_INFO_PRINT(F("Run non blocking command: ")); - CD_INFO_PRINTLN(tCommandName); + INFO_PRINT(F("Run non blocking command: ")); + INFO_PRINTLN(tCommandName); #if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* * Do (non blocking) buzzer feedback before command is executed @@ -297,14 +369,11 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate } #endif IRMapping[i].CommandToCall(); - } - else - { + } else { /* * Blocking command here */ - if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) - { + if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) { /* * Here no blocking command was running and we are called from main loop */ @@ -316,8 +385,8 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate /* * This call is blocking!!! */ - CD_INFO_PRINT(F("Run blocking command: ")); - CD_INFO_PRINTLN(tCommandName); + INFO_PRINT(F("Run blocking command: ")); + INFO_PRINTLN(tCommandName); #if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* @@ -329,13 +398,10 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate #endif IRMapping[i].CommandToCall(); -#if defined(TRACE) - Serial.println(F("End of blocking command")); -#endif + TRACE_PRINTLN(F("End of blocking command")); + currentBlockingCommandCalled = COMMAND_EMPTY; - } - else - { + } else { /* * Called by ISR or another command still running. * Do not run command directly, but set request to stop to true and store command @@ -343,9 +409,9 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate */ BlockingCommandToRunNext = IRReceivedData.command; requestToStopReceived = true; // to stop running command - CD_INFO_PRINT(F("Requested stop and stored blocking command ")); - CD_INFO_PRINT(tCommandName); - CD_INFO_PRINTLN(F(" as next command to run.")); + INFO_PRINT(F("Requested stop and stored blocking command ")); + INFO_PRINT(tCommandName); + INFO_PRINTLN(F(" as next command to run.")); } } break; // command found @@ -358,16 +424,14 @@ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediate * Intended to be called from main loop * @return true, if command was called */ -bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() -{ +bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { /* * Take last rejected command and call associated function */ - if (BlockingCommandToRunNext != COMMAND_EMPTY) - { + if (BlockingCommandToRunNext != COMMAND_EMPTY) { - CD_INFO_PRINT(F("Run stored command=0x")); - CD_INFO_PRINTLN(BlockingCommandToRunNext, HEX); + INFO_PRINT(F("Run stored command=0x")); + INFO_PRINTLN(BlockingCommandToRunNext, HEX); IRReceivedData.command = BlockingCommandToRunNext; BlockingCommandToRunNext = COMMAND_EMPTY; @@ -382,14 +446,9 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() /* * Not used internally */ -#if defined(IR_COMMAND_HAS_MORE_THAN_8_BIT) -void IRCommandDispatcher::setNextBlockingCommand(uint16_t aBlockingCommandToRunNext) -#else -void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNext) -#endif -{ - CD_INFO_PRINT(F("Set next command to run to 0x")); - CD_INFO_PRINTLN(aBlockingCommandToRunNext, HEX); +void IRCommandDispatcher::setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext) { + INFO_PRINT(F("Set next command to run to 0x")); + INFO_PRINTLN(aBlockingCommandToRunNext, HEX); BlockingCommandToRunNext = aBlockingCommandToRunNext; requestToStopReceived = true; } @@ -399,42 +458,48 @@ void IRCommandDispatcher::setNextBlockingCommand(uint8_t aBlockingCommandToRunNe * To be used in blocking functions as delay * @return true - as soon as stop received */ -bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) -{ +bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) { uint32_t tStartMillis = millis(); - do - { - if (requestToStopReceived) - { + do { + if (requestToStopReceived) { return true; } - } - while (millis() - tStartMillis < aDelayMillis); + } while (millis() - tStartMillis < aDelayMillis); return false; } -void IRCommandDispatcher::printIRCommandString(Print *aSerial) -{ - for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) - { - if (IRReceivedData.command == IRMapping[i].IRCode) - { - aSerial->println(reinterpret_cast(IRMapping[i].CommandString)); +void IRCommandDispatcher::printIRCommandString(Print *aSerial, uint_fast8_t aMappingArrayIndex) { +#if defined(__AVR__) +# if defined(USE_DISPATCHER_COMMAND_STRINGS) + aSerial->println(reinterpret_cast(IRMapping[aMappingArrayIndex].CommandString)); +# else + aSerial->print(F("0x")); + aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX); +# endif +#else +# if defined(USE_DISPATCHER_COMMAND_STRINGS) + aSerial->println(IRMapping[aMappingArrayIndex].CommandString); +# else + aSerial->print("0x"); + aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX); +# endif +#endif +} + +void IRCommandDispatcher::printIRCommandString(Print *aSerial) { + for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { + if (IRReceivedData.command == IRMapping[i].IRCode) { + printIRCommandString(aSerial, i); return; } } aSerial->println(F("unknown")); } -void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) -{ +void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) { requestToStopReceived = aRequestToStopReceived; } -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif -#if defined(LOCAL_INFO) -#undef LOCAL_INFO -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_COMMAND_DISPATCHER_HPP diff --git a/src/IRProtocol.h b/src/IRProtocol.h index 4704ab895..e7527624a 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -149,8 +149,8 @@ struct PulseDistanceWidthProtocolConstants { * Definitions for member PulseDistanceWidthProtocolConstants.Flags */ #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_DISTANCE_WIDTH 0x00 // Can often be decoded successfully as pulse distance +#define PROTOCOL_IS_PULSE_WIDTH 0x10 // Currently only Sony protocol #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 diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 72f6999e5..7d2c5c455 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -33,12 +33,6 @@ #ifndef _IR_PROTOCOL_HPP #define _IR_PROTOCOL_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif - /** \addtogroup Receiving Receiving IR data for multiple protocols * @{ */ @@ -138,11 +132,21 @@ size_t print(PrintImplType *p, unsigned long long value, int base) { tLength += p->print(static_cast(value), base); return tLength; } +template::value, bool>::type = true> +size_t println(PrintImplType *p, unsigned long long value, int base) { + size_t tLength = p->print(static_cast(value >> 32), base); + tLength += p->println(static_cast(value), base); + return tLength; +} template::value, bool>::type = true> size_t print(PrintImplType *p, unsigned long long value, int base) { return p->print(value, base); } +template::value, bool>::type = true> +size_t println(PrintImplType *p, unsigned long long value, int base) { + return p->println(value, base); +} } ; # else @@ -150,6 +154,9 @@ namespace PrintULL { size_t print(Print *aSerial, unsigned long long n, int base) { return aSerial->print(n, base); } + size_t println(Print *aSerial, unsigned long long n, int base) { + return aSerial->println(n, base); + } }; # endif #endif @@ -186,7 +193,4 @@ uint32_t bitreverse32Bit(uint32_t aInput) { /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif #endif // _IR_PROTOCOL_HPP diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 1fbb66725..ee8562d09 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -33,17 +33,9 @@ #ifndef _IR_RECEIVE_HPP #define _IR_RECEIVE_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif - -#if defined(TRACE) && !defined(LOCAL_TRACE) -#define LOCAL_TRACE -#else -//#define LOCAL_TRACE // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /* * Low level hardware timing measurement */ @@ -153,16 +145,16 @@ void IRrecv::ReceiveInterruptHandler() { 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 + * Here we are just resumed and wait for start bit. But in real time we may be in the middle of an ongoing 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 + // Check if we are not in the middle of an ongoing transmission by checking the minimum length of leading space 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 /* - * Gap between two transmissions just ended; Record gap duration + start recording transmission + * Big gap between two transmissions just ended; Record gap duration + start recording transmission * Initialize all state machine variables */ irparams.OverflowFlag = false; @@ -197,7 +189,7 @@ void IRrecv::ReceiveInterruptHandler() { } else if (tStateForISR == IR_REC_STATE_SPACE) { /* - * In space receiving here, rawlen is odd + * Timing space here, rawlen is odd * Check for timeout or overflow */ if (tTickCounterForISR > RECORD_GAP_TICKS || irparams.rawlen >= RAW_BUFFER_LENGTH - 1) { @@ -228,6 +220,9 @@ void IRrecv::ReceiveInterruptHandler() { * Call callback if registered (not nullptr) */ if (irparams.ReceiveCompleteCallbackFunction != nullptr) { +#if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) && !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled + interrupts(); // To enable the receiving for the other instances while in callback +#endif irparams.ReceiveCompleteCallbackFunction(); } #endif @@ -510,11 +505,10 @@ void IRrecv::initDecodedIRData() { if (irparams.OverflowFlag) { decodedIRData.flags = IRDATA_FLAGS_WAS_OVERFLOW; -#if defined(LOCAL_DEBUG) - Serial.print(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of ")); - Serial.print(RAW_BUFFER_LENGTH); - Serial.println(F(" with #define RAW_BUFFER_LENGTH=")); -#endif + + DEBUG_PRINT(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of ")); + DEBUG_PRINT(RAW_BUFFER_LENGTH); + DEBUG_PRINTLN(F(" with #define RAW_BUFFER_LENGTH=")); } else { decodedIRData.flags = IRDATA_FLAGS_EMPTY; @@ -589,28 +583,28 @@ bool IRrecv::decode() { } #if defined(DECODE_NEC) || defined(DECODE_ONKYO) - IR_TRACE_PRINTLN(F("Attempting NEC/Onkyo decode")); + TRACE_PRINTLN(F("Attempting NEC/Onkyo decode")); if (decodeNEC()) { return true; } #endif #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) - IR_TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode")); + TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode")); if (decodeKaseikyo()) { return true; } #endif #if defined(DECODE_DENON) - IR_TRACE_PRINTLN(F("Attempting Denon/Sharp decode")); + TRACE_PRINTLN(F("Attempting Denon/Sharp decode")); if (decodeDenon()) { return true; } #endif #if defined(DECODE_SONY) - IR_TRACE_PRINTLN(F("Attempting Sony decode")); + TRACE_PRINTLN(F("Attempting Sony decode")); if (decodeSony()) { return true; } @@ -618,11 +612,11 @@ bool IRrecv::decode() { #if defined(DECODE_RC5) || defined(DECODE_MARANTZ) # if defined(DECODE_RC5) && !defined(DECODE_MARANTZ) - IR_TRACE_PRINTLN(F("Attempting RC5 decode")); + TRACE_PRINTLN(F("Attempting RC5 decode")); # elif !defined(DECODE_RC5) && defined(DECODE_MARANTZ) - IR_TRACE_PRINTLN(F("Attempting Marantz decode")); + TRACE_PRINTLN(F("Attempting Marantz decode")); # else - IR_TRACE_PRINTLN(F("Attempting RC5 and Marantz decode")); + TRACE_PRINTLN(F("Attempting RC5 and Marantz decode")); # endif if (decodeRC5()) { return true; @@ -630,28 +624,28 @@ bool IRrecv::decode() { #endif #if defined(DECODE_RC6) - IR_TRACE_PRINTLN(F("Attempting RC6 decode")); + TRACE_PRINTLN(F("Attempting RC6 decode")); if (decodeRC6()) { return true; } #endif #if defined(DECODE_LG) - IR_TRACE_PRINTLN(F("Attempting LG decode")); + TRACE_PRINTLN(F("Attempting LG decode")); if (decodeLG()) { return true; } #endif #if defined(DECODE_JVC) - IR_TRACE_PRINTLN(F("Attempting JVC decode")); + TRACE_PRINTLN(F("Attempting JVC decode")); if (decodeJVC()) { return true; } #endif #if defined(DECODE_SAMSUNG) - IR_TRACE_PRINTLN(F("Attempting Samsung decode")); + TRACE_PRINTLN(F("Attempting Samsung decode")); if (decodeSamsung()) { return true; } @@ -661,49 +655,49 @@ bool IRrecv::decode() { */ #if defined(DECODE_BEO) - IR_TRACE_PRINTLN(F("Attempting Bang & Olufsen decode")); + TRACE_PRINTLN(F("Attempting Bang & Olufsen decode")); if (decodeBangOlufsen()) { return true; } #endif #if defined(DECODE_FAST) - IR_TRACE_PRINTLN(F("Attempting FAST decode")); + TRACE_PRINTLN(F("Attempting FAST decode")); if (decodeFAST()) { return true; } #endif #if defined(DECODE_WHYNTER) - IR_TRACE_PRINTLN(F("Attempting Whynter decode")); + TRACE_PRINTLN(F("Attempting Whynter decode")); if (decodeWhynter()) { return true; } #endif #if defined(DECODE_LEGO_PF) - IR_TRACE_PRINTLN(F("Attempting Lego Power Functions")); + TRACE_PRINTLN(F("Attempting Lego Power Functions")); if (decodeLegoPowerFunctions()) { return true; } #endif #if defined(DECODE_BOSEWAVE) - IR_TRACE_PRINTLN(F("Attempting Bosewave decode")); + TRACE_PRINTLN(F("Attempting Bosewave decode")); if (decodeBoseWave()) { return true; } #endif #if defined(DECODE_MAGIQUEST) - IR_TRACE_PRINTLN(F("Attempting MagiQuest decode")); + TRACE_PRINTLN(F("Attempting MagiQuest decode")); if (decodeMagiQuest()) { return true; } #endif #if defined(DECODE_OPENLASIR) - IR_TRACE_PRINTLN(F("Attempting OpenLASIR decode")); + TRACE_PRINTLN(F("Attempting OpenLASIR decode")); if (decodeOpenLASIR()) { return true; } @@ -713,7 +707,7 @@ bool IRrecv::decode() { * Try the universal decoder for pulse distance protocols */ #if defined(DECODE_DISTANCE_WIDTH) - IR_TRACE_PRINTLN(F("Attempting universal Distance Width decode")); + TRACE_PRINTLN(F("Attempting universal Distance Width decode")); if (decodeDistanceWidth()) { return true; } @@ -723,7 +717,7 @@ bool IRrecv::decode() { * Last resort is the universal hash decode which always return true */ #if defined(DECODE_HASH) - IR_TRACE_PRINTLN(F("Hash decode")); + TRACE_PRINTLN(F("Hash decode")); // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. @@ -743,6 +737,7 @@ bool IRrecv::decode() { **********************************************************************************************************************/ /** * 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! + * We do not check the length of the constant pulse for the widely used PulseDistance width and the constant pause for PulseWidth (currently only sony protocol). * using matchMark() and matchSpace(), which includes MARK_EXCESS_MICROS in comparison. * * We can have the following protocol timings @@ -762,15 +757,13 @@ bool IRrecv::decode() { void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMicros, bool aIsPulseWidthProtocol, bool aMSBfirst) { -#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 + DEBUG_PRINT(F("aOneMicros=")); + DEBUG_PRINT(aOneMicros); + DEBUG_PRINT(F(", 0.75*aOneMicros=")); + DEBUG_PRINT((aOneMicros * 3) / 4); + DEBUG_PRINT(F(", MARK_EXCESS_MICROS=" STR(MARK_EXCESS_MICROS) " isPulseWidthProtocol=")); + DEBUG_PRINT(aIsPulseWidthProtocol); + DEBUG_PRINTLN(); IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop IRRawDataType tMask = 1UL; // Mask is only used for LSB first @@ -809,12 +802,12 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } else { tDecodedData |= tMask; } - IR_TRACE_PRINT(tCurrentTicks); - IR_TRACE_PRINTLN(F(" => 1")); + TRACE_PRINT(tCurrentTicks); + TRACE_PRINTLN(F(" => 1")); } else { // do not set the bit - IR_TRACE_PRINT(tCurrentTicks); - IR_TRACE_PRINTLN(F(" => 0")); + TRACE_PRINT(tCurrentTicks); + TRACE_PRINTLN(F(" => 0")); } tMask <<= 1; } @@ -842,13 +835,11 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy 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 + DEBUG_PRINT(F("OneThresholdMicros=")); + DEBUG_PRINT(aOneThresholdMicros); + DEBUG_PRINT(F(" isPulseWidthProtocol=")); + DEBUG_PRINT(aIsPulseWidthProtocol); + DEBUG_PRINTLN(); IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop IRRawDataType tMask = 1UL; // Mask is only used for LSB first @@ -878,12 +869,12 @@ void IRrecv::decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBit } else { tDecodedData |= tMask; } - IR_TRACE_PRINT(tCurrentMicros); - IR_TRACE_PRINTLN(F(" => 1")); + TRACE_PRINT(tCurrentMicros); + TRACE_PRINTLN(F(" => 1")); } else { // do not set the bit - IR_TRACE_PRINT(tCurrentMicros); - IR_TRACE_PRINTLN(F(" => 0")); + TRACE_PRINT(tCurrentMicros); + TRACE_PRINTLN(F(" => 0")); } tMask <<= 1; } @@ -939,10 +930,10 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy } else { tDecodedData |= tMask; } - IR_TRACE_PRINTLN(F("=> 1")); + TRACE_PRINTLN(F("=> 1")); } else { // do not set the bit - IR_TRACE_PRINTLN(F("=> 0")); + TRACE_PRINTLN(F("=> 0")); } tMask <<= 1; } @@ -996,29 +987,25 @@ bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRa // Check for constant mark duration if (!matchMark(tMarkTicks, aOneMarkMicros)) { -#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(". Index=")); - Serial.print(aNumberOfBits - i); - Serial.print(' '); -#endif + DEBUG_PRINT(F("Mark=")); + DEBUG_PRINT(tMarkTicks * MICROS_PER_TICK); + DEBUG_PRINT(F(" is not ")); + DEBUG_PRINT(aOneMarkMicros); + DEBUG_PRINT(F(". Index=")); + DEBUG_PRINT(aNumberOfBits - i); + DEBUG_PRINT(' '); 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 + DEBUG_PRINT(F("Space=")); + DEBUG_PRINT(tSpaceTicks * MICROS_PER_TICK); + DEBUG_PRINT(F(" is not ")); + DEBUG_PRINT(aZeroSpaceMicros); + DEBUG_PRINT(F(". Index=")); + DEBUG_PRINT(aNumberOfBits - i); + DEBUG_PRINT(' '); return false; } @@ -1034,29 +1021,25 @@ bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRa // 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 + DEBUG_PRINT(F("Space=")); + DEBUG_PRINT(tSpaceTicks * MICROS_PER_TICK); + DEBUG_PRINT(F(" is not ")); + DEBUG_PRINT(aOneSpaceMicros); + DEBUG_PRINT(F(" or ")); + DEBUG_PRINT(aZeroSpaceMicros); + DEBUG_PRINT(F(". Index=")); + DEBUG_PRINT(aNumberOfBits - i); + DEBUG_PRINT(' '); 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 + DEBUG_PRINT(F("Mark=")); + DEBUG_PRINT(tMarkTicks * MICROS_PER_TICK); + DEBUG_PRINT(F(" is not ")); + DEBUG_PRINT(aZeroMarkMicros); + DEBUG_PRINT(F(". Index=")); + DEBUG_PRINT(aNumberOfBits - i); + DEBUG_PRINT(' '); return false; } } @@ -1072,10 +1055,10 @@ bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRa } else { tDecodedData |= tMask; } - IR_TRACE_PRINTLN(F("=> 1")); + TRACE_PRINTLN(F("=> 1")); } else { // do not set the bit - IR_TRACE_PRINTLN(F("=> 0")); + TRACE_PRINTLN(F("=> 0")); } tMask <<= 1; } @@ -1181,10 +1164,9 @@ bool IRrecv::decodeHash() { // Require at least 6 samples to prevent triggering on noise if (decodedIRData.rawlen < 6) { - IR_DEBUG_PRINT(F("HASH: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is less than 6")); + DEBUG_PRINT(F("HASH: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is less than 6")); return false; } for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) { @@ -1233,17 +1215,13 @@ bool IRrecv::decodeHashOld(decode_results *aResults) { bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants) { // Check header "mark" and "space" 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 + TRACE_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex)); + TRACE_PRINTLN(F(": Header mark length is wrong")); 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 + TRACE_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex)); + TRACE_PRINTLN(F(": Header space length is wrong")); return false; } return true; @@ -1252,17 +1230,13 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants 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((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); - Serial.println(F(": Header mark length is wrong")); -#endif + TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); + TRACE_PRINTLN(F(": Header mark length is wrong")); return false; } if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { -#if defined(LOCAL_TRACE) - Serial.print(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); - Serial.println(F(": Header space length is wrong")); -#endif + TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); + TRACE_PRINTLN(F(": Header space length is wrong")); return false; } return true; @@ -1286,24 +1260,24 @@ void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTick /** * Match function WITHOUT compensating for marks exceeded or spaces shortened by demodulator hardware - * Match is true, if signal value is bigger/equal 75% and less/equal 125% of match value. + * Match is true, if signal value is bigger/equal 75% and less/equal 125% of aMatchValueMicros. * @return true, if values match */ 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 (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 + + TRACE_PRINT(F("Testing (actual vs desired): ")); + TRACE_PRINT(tMeasuredMicros); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 3); // rounded value because we divide first + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 5); + bool passed = (tMeasuredMicros >= (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5)); #if defined(LOCAL_TRACE) if (passed) { @@ -1322,18 +1296,18 @@ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { 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 + + TRACE_PRINT(F("Testing (actual vs desired): ")); + TRACE_PRINT(tMeasuredMicros); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 3); // rounded value because we divide first + TRACE_PRINT(F(" < ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 5); + bool passed = (tMeasuredMicros > (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5)); #if defined(LOCAL_TRACE) if (passed) { @@ -1363,21 +1337,21 @@ bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { // 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 + + TRACE_PRINT(F("Testing mark (actual vs desired): ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); +// TRACE_PRINT(F("TICKS_LOW=")); +// TRACE_PRINT(TICKS_LOW(aMatchValueMicros)); +// TRACE_PRINT(F(" ")); + TRACE_PRINT(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK); + // compensate for marks exceeded by demodulator hardware bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros))); @@ -1409,21 +1383,21 @@ bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { # 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 + + TRACE_PRINT(F("Testing space (actual vs desired): ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); + TRACE_PRINT(F("LOW=")); + TRACE_PRINT(TICKS_LOW(aMatchValueMicros)); + TRACE_PRINT(F(" ")); + TRACE_PRINT(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK); + // compensate for spaces shortened by demodulator hardware bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros))); @@ -1581,11 +1555,11 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) aSerial->print(getProtocolString()); if (decodedIRData.protocol == UNKNOWN) { #if defined(DECODE_HASH) - aSerial->print(F(" Hash=0x")); + aSerial->print(F(" Hash=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 @@ -1631,7 +1605,7 @@ bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) #if (__INT_WIDTH__ < 32) aSerial->print(decodedIRData.decodedRawData, HEX); #else - PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); + PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); #endif aSerial->print(F(", ")); @@ -1811,7 +1785,7 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) { #if (__INT_WIDTH__ < 32) aSerial->print(aIRDataPtr->decodedRawData, HEX); #else - PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX); + PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX); #endif /* * Print number of bits processed @@ -2119,7 +2093,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)) { @@ -2289,8 +2263,10 @@ void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInste tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; aSerial->print(tTicks); } - if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one - if (!(i & 1)) aSerial->print(' '); + if (i + 1 < decodedIRData.rawlen) + aSerial->print(','); // ',' not required on last one + if (!(i & 1)) + aSerial->print(' '); } // End declaration @@ -2357,12 +2333,12 @@ void IRrecv::printIRResultAsCVariables(Print *aSerial) { #if __INT_WIDTH__ < 32 aSerial->print(F("uint32_t rawIRTimings = 0x")); #else - aSerial->print(F("uint64_t rawIRTimings = 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(';'); } @@ -2374,10 +2350,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 /********************************************************************************************************************** @@ -2403,7 +2379,7 @@ bool IRrecv::decode_old(decode_results *aResults) { // Copy overflow flag to decodedIRData.flags irparams.OverflowFlag = false; irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call - IR_DEBUG_PRINTLN(F("Overflow happened")); + DEBUG_PRINTLN(F("Overflow happened")); } aResults->overflow = irparams.OverflowFlag; aResults->value = 0; @@ -2411,21 +2387,21 @@ 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")); + 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")); + DEBUG_PRINTLN(F("Attempting old Sony decode")); if (decodeSonyMSB(aResults)) { return true; } #endif #if defined(DECODE_RC5) - IR_DEBUG_PRINTLN(F("Attempting RC5 decode")); + DEBUG_PRINTLN(F("Attempting RC5 decode")); if (decodeRC5()) { aResults->bits = decodedIRData.numberOfBits; aResults->value = decodedIRData.decodedRawData; @@ -2436,7 +2412,7 @@ bool IRrecv::decode_old(decode_results *aResults) { #endif #if defined(DECODE_RC6) - IR_DEBUG_PRINTLN(F("Attempting RC6 decode")); + DEBUG_PRINTLN(F("Attempting RC6 decode")); if (decodeRC6()) { aResults->bits = decodedIRData.numberOfBits; aResults->value = decodedIRData.decodedRawData; @@ -2448,26 +2424,26 @@ bool IRrecv::decode_old(decode_results *aResults) { // 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")); + 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")); + 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")); + 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")); + DEBUG_PRINTLN(F("Attempting old Denon decode")); if (decodeDenonOld(aResults)) { return true; } @@ -2488,10 +2464,6 @@ bool IRrecv::decode_old(decode_results *aResults) { #if defined(_IR_MEASURE_TIMING) #undef _IR_MEASURE_TIMING #endif -#if defined(LOCAL_TRACE) -#undef LOCAL_TRACE -#endif -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_RECEIVE_HPP diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 0cab2c010..d338ad8cd 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -32,17 +32,10 @@ #ifndef _IR_SEND_HPP #define _IR_SEND_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif - -#if defined(TRACE) && !defined(LOCAL_TRACE) -#define LOCAL_TRACE -#else -//#define LOCAL_TRACE // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" /* * Low level hardware timing measurement @@ -408,13 +401,11 @@ void IRsend::sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast16_t aLe // Set IR carrier frequency enableIROut(aIRFrequencyKilohertz); -#if defined(LOCAL_DEBUG) - Serial.print(F("aPGMBufferWithMicroseconds=0x")); - Serial.print((uint32_t) aBufferWithMicroseconds, HEX); - Serial.print(F(" [0]=")); - Serial.println(aBufferWithMicroseconds[0]); // this crashes on ESP8266 if aBufferWithMicroseconds is PROGMEM - Serial.flush(); -#endif + DEBUG_PRINT(F("aPGMBufferWithMicroseconds=0x")); + DEBUG_PRINT((uint32_t) aBufferWithMicroseconds, HEX); + DEBUG_PRINT(F(" [0]=")); + DEBUG_PRINTLN(aBufferWithMicroseconds[0]); // this crashes on ESP8266 if aBufferWithMicroseconds is PROGMEM + DEBUG_FLUSH(); /* * Raw data starts with a mark. @@ -509,11 +500,9 @@ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_ /* * 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 + DEBUG_PRINT(F("aPGMBufferWithMicroseconds=0x")); + DEBUG_PRINTLN((uint16_t) aPGMBufferWithMicroseconds, HEX); for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) { uint16_t duration = pgm_read_word(&aPGMBufferWithMicroseconds[i]); @@ -521,18 +510,12 @@ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_ if (i & 1) { // Odd space(duration); -# if defined(LOCAL_DEBUG) - Serial.print(F("S=")); -# endif + DEBUG_PRINT(F("S=")); } else { mark(duration); -# if defined(LOCAL_DEBUG) - Serial.print(F("M=")); -# endif + DEBUG_PRINT(F("M=")); } -# if defined(LOCAL_DEBUG) - Serial.println(duration); -# endif + DEBUG_PRINTLN(duration); } #endif } @@ -540,13 +523,11 @@ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_ void IRsend::sendRaw_P(const uint16_t aPGMBufferWithMicroseconds[], uint_fast16_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz, uint_fast16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { -#if defined(LOCAL_DEBUG) - Serial.print(F("aPGMBufferWithMicroseconds=0x")); - Serial.print((uint32_t) aPGMBufferWithMicroseconds, HEX); - Serial.print(F(" [0]=")); - Serial.println(aPGMBufferWithMicroseconds[0]); // this crashes on ESP8266 - Serial.flush(); -#endif + DEBUG_PRINT(F("aPGMBufferWithMicroseconds=0x")); + DEBUG_PRINT((uint32_t) aPGMBufferWithMicroseconds, HEX); + DEBUG_PRINT(F(" [0]=")); + DEBUG_PRINTLN(aPGMBufferWithMicroseconds[0]); // this crashes on ESP8266 + DEBUG_FLUSH(); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { @@ -584,18 +565,12 @@ void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengt if (i & 1) { // Odd space(duration); -# if defined(LOCAL_DEBUG) - Serial.print(F("S=")); -# endif + DEBUG_PRINT(F("S=")); } else { mark(duration); -# if defined(LOCAL_DEBUG) - Serial.print(F("M=")); -# endif + DEBUG_PRINT(F("M=")); } -# if defined(LOCAL_DEBUG) - Serial.println(duration); -# endif + DEBUG_PRINTLN(duration); } #endif } @@ -636,26 +611,20 @@ void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengt 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 + DEBUG_PRINT(aData, HEX); + DEBUG_PRINT('|'); + DEBUG_PRINTLN(aNumberOfBits); + DEBUG_FLUSH(); // 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 + TRACE_PRINT('1'); mark(aOneMarkMicros); space(aOneSpaceMicros); } else { -#if defined(LOCAL_TRACE) - Serial.print('0'); -#endif + TRACE_PRINT('0'); mark(aZeroMarkMicros); space(aZeroSpaceMicros); } @@ -672,14 +641,10 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp */ if ((!(aFlags & SUPPRESS_STOP_BIT)) && (uintDifferenceAbs(aOneSpaceMicros, aZeroSpaceMicros) > (aOneSpaceMicros / 4))) { // Send stop bit here -#if defined(LOCAL_TRACE) - Serial.print('S'); -#endif + TRACE_PRINT('S'); mark(aOneMarkMicros); // Use aOneMarkMicros for stop bits. This seems to be correct for all protocols :-) } -#if defined(LOCAL_TRACE) - Serial.println(); -#endif + TRACE_PRINTLN(); } /********************************************************************************************************************** @@ -952,13 +917,11 @@ void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz, void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { -#if defined(LOCAL_DEBUG) - Serial.print(F("Data=0x")); - Serial.print(aData, HEX); - Serial.print(F(" #=")); - Serial.println(aNumberOfBits); - Serial.flush(); -#endif + DEBUG_PRINT(F("Data=0x")); + DEBUG_PRINT(aData, HEX); + DEBUG_PRINT(F(" #=")); + DEBUG_PRINTLN(aNumberOfBits); + DEBUG_FLUSH(); if (aNumberOfRepeats < 0) { if (aProtocolConstants->SpecialSendRepeatFunction != nullptr) { @@ -1207,19 +1170,16 @@ void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const * Send an additional start bit if specified * 0 -> mark+space * 1 -> space+mark - * The output always ends with a space - * @param aData uint32 or uint64 holding the bits to be sent. + * The output always ends with a space / inactive level + * @param aData uint32 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, bool aSendStartBit) { - IR_TRACE_PRINT(F("0x")); - IR_TRACE_PRINT(aData, HEX); - -#if defined(LOCAL_TRACE) - Serial.print('S'); -#endif + TRACE_PRINT(F("0x")); + TRACE_PRINT(aData, HEX); + TRACE_PRINT('S'); // Data - Biphase code MSB first @@ -1247,9 +1207,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas tMask >>= 1; tNextBitIsOne = ((aData & tMask) != 0) || (i == 1); // true for last bit to avoid extension of mark if (tCurrentBitIsOne) { -#if defined(LOCAL_TRACE) - Serial.print('1'); -#endif + TRACE_PRINT('1'); space(aBiphaseTimeUnit); if (tNextBitIsOne) { mark(aBiphaseTimeUnit); // if next bit is 1 send a single mark @@ -1260,9 +1218,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas tLastBitWasOne = true; } else { -#if defined(LOCAL_TRACE) - Serial.print('0'); -#endif + TRACE_PRINT('0'); if (!tLastBitWasOne) { mark(aBiphaseTimeUnit); // if last bit was 0 send a single mark } @@ -1270,7 +1226,7 @@ void IRsend::sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fas tLastBitWasOne = false; } } - IR_TRACE_PRINTLN(); + TRACE_PRINTLN(); } /** @@ -1604,10 +1560,6 @@ uint16_t IRsend::getPulseCorrectionNanos() { #if defined(_IR_MEASURE_TIMING) #undef _IR_MEASURE_TIMING #endif -#if defined(LOCAL_TRACE) -#undef LOCAL_TRACE -#endif -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_SEND_HPP diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 1655279e7..75efff709 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -115,7 +115,7 @@ /** * Minimum gap between IR transmissions, to detect the end of a protocol. * Must be greater than any space of a protocol e.g. the NEC header space of 4500 us. - * Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 15 ms for Sony20 protocol. + * Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 12 ms for Sony20 protocol. * Keep in mind, that this is the delay between the end of the received command and the start of decoding. */ #if !defined(RECORD_GAP_MICROS) @@ -123,6 +123,8 @@ // Maximum value for RECORD_GAP_MICROS, which fit into 8 bit buffer, using 50 us as tick, is 12750 #define RECORD_GAP_MICROS 8000 // RECS80 (https://www.mikrocontroller.net/articles/IRMP#RECS80) 1 bit space is 7500µs , NEC header space is 4500 #endif +#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 160 + /** * Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value. */ @@ -131,9 +133,6 @@ #define RECORD_GAP_MICROS_WARNING_THRESHOLD 15000 #endif -/** Minimum gap between IR transmissions, in MICROS_PER_TICK */ -#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) - /* * Activate this line if your receiver has an external output driver transistor / "inverted" output */ diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index ec598ebcb..605de5734 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -134,6 +134,13 @@ struct irparams_struct { volatile uint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is independent of state or resume(). #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK) void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP +#endif +#if defined(DECODE_RC5) || defined(DECODE_RC6) || defined(DECODE_MARANTZ) + // Static variables for the getBiphaselevel() function + uint_fast8_t RawbuffOffsetForNextBiphaseLevel; // Index into raw timing array + uint16_t NumberOfTimingIntervalsInCurrentInterval; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[RawbuffOffsetForNextBiphaseLevel] timing. + uint_fast8_t AlreadyUsedTimingIntervalsOfCurrentInterval; // Number of already used intervals of sCurrentTimingIntervals. + uint16_t BiphaseTimeUnit; #endif bool OverflowFlag; ///< Raw buffer OverflowFlag occurred IRRawlenType rawlen; ///< counter of entries in rawbuf @@ -172,33 +179,6 @@ struct IRData { uint16_t initialGapTicks; ///< Contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame. }; -/* - * Debug directives - * Outputs with IR_DEBUG_PRINT can only be activated by defining DEBUG! - * If LOCAL_DEBUG is defined in one file, all outputs with IR_DEBUG_PRINT are still suppressed. - */ -#if defined(DEBUG) || defined(TRACE) -# define IR_DEBUG_PRINT(...) Serial.print(__VA_ARGS__) -# define IR_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) -#else -/** - * If DEBUG, print the arguments, otherwise do nothing. - */ -# define IR_DEBUG_PRINT(...) void() -/** - * If DEBUG, print the arguments as a line, otherwise do nothing. - */ -# define IR_DEBUG_PRINTLN(...) void() -#endif - -#if defined(TRACE) -# define IR_TRACE_PRINT(...) Serial.print(__VA_ARGS__) -# define IR_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__) -#else -# define IR_TRACE_PRINT(...) void() -# define IR_TRACE_PRINTLN(...) void() -#endif - /**************************************************** * RECEIVING ****************************************************/ @@ -341,11 +321,11 @@ class IRrecv { 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); - +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6) void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit); + static uint8_t getNumberOfUnitsInInterval(uint16_t aCurrentInterval, uint16_t aTimeUnit); uint_fast8_t getBiphaselevel(); +#endif /* * All standard (decode address + command) protocol decoders @@ -361,8 +341,12 @@ class IRrecv { bool decodeMagiQuest(); // not completely standard bool decodeNEC(); bool decodeOpenLASIR(); +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) bool decodeRC5(); +#endif +#if defined(DECODE_RC6) bool decodeRC6(); +#endif bool decodeSamsung(); bool decodeSharp(); // redirected to decodeDenon() bool decodeSony(); @@ -429,8 +413,6 @@ void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) // 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 */ @@ -720,8 +702,14 @@ class IRsend { sendNECMSB(aRawData, nbits); } void sendNECMSB(uint32_t data, uint8_t nbits, bool repeat = false); - void sendRC5(uint32_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead.")));; - void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead.")));; + void sendRC5(uint32_t data, + uint8_t nbits) + __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead."))); + ; + void sendRC5ext(uint8_t addr, uint8_t cmd, + bool toggle) + __attribute__ ((deprecated ("Please use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead."))); + ; void sendRC6Raw(uint32_t data, uint8_t nbits); void sendRC6(uint32_t data, uint8_t nbits) __attribute__ ((deprecated ("Please use sendRC6Raw()."))); void sendRC6Raw(uint64_t data, uint8_t nbits); diff --git a/src/LocalDebugLevelEnd.h b/src/LocalDebugLevelEnd.h new file mode 100644 index 000000000..ff64634f8 --- /dev/null +++ b/src/LocalDebugLevelEnd.h @@ -0,0 +1,45 @@ +/* + * LocalDebugLevelEnd.h + * Undefine local macros at the end of an included (.hpp) file + * + * Copyright (C) 2024 Armin Joachimsmeyer + * Email: armin.joachimsmeyer@gmail.com + * + * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. + * + * Arduino-Utils is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public INFOse for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* + * Undefine local macros at the end of an included (.hpp) file + */ +#if defined(LOCAL_TRACE) +#undef LOCAL_TRACE +#endif +#undef TRACE_PRINT +#undef TRACE_PRINTLN +#undef TRACE_FLUSH +#if defined(LOCAL_DEBUG) +#undef LOCAL_DEBUG +#endif +#undef DEBUG_PRINT +#undef DEBUG_PRINTLN +#undef DEBUG_FLUSH +#if defined(LOCAL_INFO) +#undef LOCAL_INFO +#endif +#undef INFO_PRINT +#undef INFO_PRINTLN +#undef INFO_FLUSH diff --git a/src/LocalDebugLevelStart.h b/src/LocalDebugLevelStart.h new file mode 100644 index 000000000..50569fbf8 --- /dev/null +++ b/src/LocalDebugLevelStart.h @@ -0,0 +1,94 @@ +/* + * LocalDebugLevelStart.h + * Include to propagate global debug levels to file local ones and to define appropriate print macros. + * !!! If used in included (.hpp) files, #include "LocalDebugLevelEnd.h" must be used at end of file to undefine local macros. + * If, for example, #define LOCAL_TRACE is placed before this include, it will not be propagated. This enables TRACE-level output to be selected only. + * + * LOCAL_TRACE // Information you need to understand details of a function or if you hunt a bug. + * LOCAL_DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. + * LOCAL_INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody". + * LOCAL_WARN // Information that the program may encounter problems, like small Heap/Stack area. + * LOCAL_ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. + * + * Copyright (C) 2024-2026 Armin Joachimsmeyer + * Email: armin.joachimsmeyer@gmail.com + * + * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. + * + * Arduino-Utils is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public INFOse for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/////////////// put this before the include ///////////////////////// +// This block must be located after the includes of other *.hpp files +//#define LOCAL_INFO // This enables info output only for this file +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development + +/* + * Propagate debug level to local ones but at first not to each other, i.e. enabling TRACE does not enable DEBUG and INFO + */ +#if defined(TRACE) // Information you need to understand details of a function or if you hunt a bug. +#define LOCAL_TRACE +# if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS) // Propagate levels by default i.e. enabling TRACE does enable DEBUG and INFO +#define LOCAL_DEBUG +#define LOCAL_INFO +# endif +#endif + +#if defined(DEBUG) // Information need to understand the operating of your program. E.g. function calls and values of control variables. +#define LOCAL_DEBUG +# if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS) +#define LOCAL_INFO +# endif +#endif + +#if defined(INFO) // Information you want to see in regular operation to see what the program is doing. E.g. "START ../src/LightToTone.cpp Version 1.2 from Dec 31 2019" or "Now playing Muppets melody". +#define LOCAL_INFO +#endif + +/* + * Define appropriate print macros + */ +#if defined(LOCAL_TRACE) +#define TRACE_PRINT(...) Serial.print(__VA_ARGS__) +#define TRACE_PRINTLN(...) Serial.println(__VA_ARGS__) +#define TRACE_FLUSH() Serial.flush() +#else +#define TRACE_PRINT(...) void() +#define TRACE_PRINTLN(...) void() +#define TRACE_FLUSH() void() +#endif + +#if defined(LOCAL_DEBUG) +#define DEBUG_PRINT(...) Serial.print(__VA_ARGS__) +#define DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) +#define DEBUG_FLUSH() Serial.flush() +#else +#define DEBUG_PRINT(...) void() +#define DEBUG_PRINTLN(...) void() +#define DEBUG_FLUSH() void() + +#endif + +#if defined(LOCAL_INFO) +#define INFO_PRINT(...) Serial.print(__VA_ARGS__) +#define INFO_PRINTLN(...) Serial.println(__VA_ARGS__) +#define INFO_FLUSH() Serial.flush() +#else +#define INFO_PRINT(...) void() +#define INFO_PRINTLN(...) void() +#define INFO_FLUSH() void() +#endif + diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index 0c4790c36..b2f313f59 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -78,7 +78,6 @@ //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. - //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define IR_RECEIVE_PIN 2 @@ -90,20 +89,16 @@ * @{ */ -#if defined(DEBUG) -#define LOCAL_DEBUG +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" +#if defined(LOCAL_DEBUG) #define LOCAL_DEBUG_ATTACH_INTERRUPT #else -//#define LOCAL_DEBUG // 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 -//#define LOCAL_TRACE_STATE_MACHINE // to see the state of the ISR (Interrupt Service Routine) state machine -#endif - //#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement. //#define _IR_TIMING_TEST_PIN 7 TinyIRReceiverStruct TinyIRReceiverControl; @@ -197,14 +192,12 @@ void IRPinChangeInterruptHandler(void) { uint8_t tState = TinyIRReceiverControl.IRReceiverState; -#if defined(LOCAL_TRACE_STATE_MACHINE) - Serial.print(tState); - Serial.print(F(" D=")); - Serial.print(tMicrosOfMarkOrSpace); -// Serial.print(F(" I=")); -// Serial.print(tIRLevel); - Serial.print('|'); -#endif + TRACE_PRINT(tState); + TRACE_PRINT(F(" D=")); + TRACE_PRINT(tMicrosOfMarkOrSpace); +// TRACE_PRINT(F(" I=")); +// TRACE_PRINT(tIRLevel); + TRACE_PRINT('|'); if (tIRLevel == LOW) { /* @@ -356,22 +349,18 @@ void IRPinChangeInterruptHandler(void) { #else TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; #endif -# if defined(LOCAL_DEBUG) - Serial.print(F("Parity check for command failed. Command=")); - Serial.print(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); - Serial.print(F(" parity=")); - Serial.println(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); -# endif + DEBUG_PRINT(F("Parity check for command failed. Command=")); + DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); + DEBUG_PRINT(F(" parity=")); + DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); #else // No address, so command and parity are in the lowest bytes if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) { TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; -# if defined(LOCAL_DEBUG) - Serial.print(F("Parity check for command failed. Command=")); - Serial.print(TinyIRReceiverControl.IRRawData.UBytes[0], HEX); - Serial.print(F(" parity=")); - Serial.println(TinyIRReceiverControl.IRRawData.UBytes[1], HEX); -# endif + DEBUG_PRINT(F("Parity check for command failed. Command=")); + DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[0], HEX); + DEBUG_PRINT(F(" parity=")); + DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[1], HEX); #endif } #endif @@ -593,7 +582,7 @@ bool enablePCIInterruptForTinyReceiver() { # 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); + attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), IRPinChangeInterruptHandler, CHANGE); // CHANGE can be an enum :-( # endif # else // USE_ATTACH_INTERRUPT_DIRECT here, only defined for ATtinies *16, see above @@ -606,7 +595,7 @@ bool enablePCIInterruptForTinyReceiver() { # endif #else # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT) - Serial.println(F("Use static interrupt for pin=" STR(IR_RECEIVE_PIN))); + Serial.println(F("Use hardware/static interrupt for pin=" STR(IR_RECEIVE_PIN))); # endif # if defined(USE_INT0) @@ -724,11 +713,6 @@ void dummyFunctionToAvoidCompilerErrors() #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT) #undef LOCAL_DEBUG_ATTACH_INTERRUPT #endif -#if defined(LOCAL_TRACE_STATE_MACHINE) -#undef LOCAL_TRACE_STATE_MACHINE -#endif +#include "LocalDebugLevelEnd.h" -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif #endif // _TINY_IR_RECEIVER_HPP diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 9412d3204..6f498b532 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -19,7 +19,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,11 +48,6 @@ //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. -#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 @@ -415,7 +410,4 @@ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif #endif // _TINY_IR_SENDER_HPP diff --git a/src/ac_LG.hpp b/src/ac_LG.hpp index d5037c2d7..6e0b3730e 100644 --- a/src/ac_LG.hpp +++ b/src/ac_LG.hpp @@ -34,12 +34,11 @@ #define _AC_LG_HPP #include -#if defined(INFO) && !defined(LOCAL_INFO) -#define LOCAL_INFO -#else -//#define LOCAL_INFO // This enables info output only for this file -#endif -//#define DEBUG // for more output from the LG-AC driver. +// This block must be located after the includes of other *.hpp files +//#define LOCAL_INFO // This enables info output only for this file +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" + #include "IRremoteInt.h" #include "ac_LG.h" // useful constants #include "LongUnion.h" @@ -63,10 +62,8 @@ const int AC_FAN_WALL[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 2, 4, 5 }; // 0 -> void Aircondition_LG::setType(bool aIsWallType) { ACIsWallType = aIsWallType; -#if defined(LOCAL_INFO) - Serial.print(F("Set wall type to ")); - Serial.println(aIsWallType); -#endif + INFO_PRINT(F("Set wall type to ")); + INFO_PRINTLN(aIsWallType); } void Aircondition_LG::printMenu(Print *aSerial) { @@ -113,7 +110,7 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { return true; case LG_COMMAND_JET: - IR_DEBUG_PRINTLN(F("Send jet on")); + DEBUG_PRINTLN(F("Send jet on")); sendIRCommand(LG_JET_ON); return true; @@ -151,7 +148,7 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { * Now the commands which require a parameter */ if (aParameter < 0) { - IR_DEBUG_PRINT(F("Error: Parameter is less than 0")); + DEBUG_PRINT(F("Error: Parameter is less than 0")); return false; } switch (aCommand) { @@ -162,8 +159,8 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { break; case LG_COMMAND_SWING: - IR_DEBUG_PRINT(F("Send air swing=")); - IR_DEBUG_PRINTLN(aParameter); + DEBUG_PRINT(F("Send air swing=")); + DEBUG_PRINTLN(aParameter); if (ACIsWallType) { if (aParameter) { sendIRCommand(LG_WALL_SWING_ON); @@ -180,8 +177,8 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { break; case LG_COMMAND_AUTO_CLEAN: - IR_DEBUG_PRINT(F("Send auto clean=")); - IR_DEBUG_PRINTLN(aParameter); + DEBUG_PRINT(F("Send auto clean=")); + DEBUG_PRINTLN(aParameter); if (aParameter) { sendIRCommand(LG_AUTO_CLEAN_ON); } else { @@ -190,8 +187,8 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { break; case LG_COMMAND_ENERGY: - IR_DEBUG_PRINT(F("Send energy saving on=")); - IR_DEBUG_PRINTLN(aParameter); + DEBUG_PRINT(F("Send energy saving on=")); + DEBUG_PRINTLN(aParameter); if (aParameter) { sendIRCommand(LG_ENERGY_SAVING_ON); } else { @@ -251,12 +248,11 @@ bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) { void Aircondition_LG::sendIRCommand(uint16_t aCommand) { -#if defined(LOCAL_INFO) - Serial.print(F("Send code=0x")); - Serial.print(aCommand, HEX); - Serial.print(F(" | 0b")); - Serial.println(aCommand, BIN); -#endif + INFO(F("Send code=0x")); + INFO_PRINT(aCommand, HEX); + INFO_PRINT(F(" | 0b")); + INFO_PRINTLN(aCommand, BIN); + IrSender.sendLG2((uint8_t) LG_ADDRESS, aCommand, 0); } @@ -267,14 +263,13 @@ void Aircondition_LG::sendIRCommand(uint16_t aCommand) { void Aircondition_LG::sendTemperatureFanSpeedAndMode() { uint8_t tTemperature = Temperature; -#if defined(LOCAL_INFO) - Serial.print(F("Send temperature=")); - Serial.print(tTemperature); - Serial.print(F(" fan intensity=")); - Serial.print(FanIntensity); - Serial.print(F(" mode=")); - Serial.println((char )Mode); -#endif + INFO_PRINT(F("Send temperature=")); + INFO_PRINT(tTemperature); + INFO_PRINT(F(" fan intensity=")); + INFO_PRINT(FanIntensity); + INFO_PRINT(F(" mode=")); + INFO_PRINTLN((char )Mode); + WordUnion tIRCommand; tIRCommand.UWord = 0; @@ -319,4 +314,6 @@ void Aircondition_LG::sendTemperatureFanSpeedAndMode() { } /** @}*/ +#include "LocalDebugLevelEnd.h" + #endif // _AC_LG_HPP diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 3c1f3015b..16ccb502d 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -34,6 +34,15 @@ #ifndef _IR_BANG_OLUFSEN_HPP #define _IR_BANG_OLUFSEN_HPP +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" + +/** \addtogroup Decoder Decoders and encoders for different protocols + * @{ + */ + //============================================================================== // // @@ -124,44 +133,26 @@ #define BEO_PULSE_LENGTH_START_BIT (5 * BEO_UNIT) // 15625 The length of the start bit // It is not allowed to send two ones or zeros, you must send a one or zero and a equal instead. -//#define BEO_LOCAL_DEBUG -//#define BEO_LOCAL_TRACE - -#ifdef BEO_LOCAL_DEBUG -# define BEO_DEBUG_PRINT(...) Serial.print(__VA_ARGS__) -# define BEO_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) -#else -# define BEO_DEBUG_PRINT(...) void() -# define BEO_DEBUG_PRINTLN(...) void() -#endif - -#ifdef BEO_LOCAL_TRACE -# undef BEO_TRACE_PRINT -# undef BEO_TRACE_PRINTLN -# define BEO_TRACE_PRINT(...) Serial.print(__VA_ARGS__) -# define BEO_TRACE_PRINTLN(...) Serial.println(__VA_ARGS__) -#else -# define BEO_TRACE_PRINT(...) void() -# define BEO_TRACE_PRINTLN(...) void() -#endif - /************************************ * Start of send and decode functions ************************************/ /* * TODO aNumberOfRepeats are handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined - * @param aNumberOfHeaderBits default is 8 + * By default 16 bits are sent. + * @param aNumberOfHeaderBits default is 8, can be 24 at maximum */ 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) { + // send 16 bits by default 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) << aNumberOfHeaderBits) | aData, aNumberOfHeaderBits + BEO_DATA_BITS, i != 0, true); + sendBangOlufsenRawDataLink((uint64_t(aHeader) << aNumberOfHeaderBits) | aData, aNumberOfHeaderBits + BEO_DATA_BITS, i != 0, + true); } } @@ -198,7 +189,7 @@ void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBack space(BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK); bool tLastBitValueWasOne = false; -// Header / Data + // Send 8 (default) to 24 bit header and 8 bit data. uint32_t mask = 1UL << (aBits - 1); for (; mask; mask >>= 1) { if (tLastBitValueWasOne && !(aRawData & mask)) { @@ -298,16 +289,14 @@ 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")); + DEBUG_PRINT(F("B&O: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + 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")); + DEBUG_PRINT(F("B&O: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not < 44")); #endif return false; } @@ -322,21 +311,20 @@ bool IRrecv::decodeBangOlufsen() { uint8_t tPulseNumber = 0; uint8_t tBitNumber = 0; - BEO_TRACE_PRINT(F("Pre gap: ")); - BEO_TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); - BEO_TRACE_PRINT(F(" raw len: ")); - BEO_TRACE_PRINTLN(decodedIRData.rawlen); + TRACE_PRINT(F("Pre gap: ")); + TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); + TRACE_PRINT(F(" raw len: ")); + TRACE_PRINTLN(decodedIRData.rawlen); #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) /* * Check if we have the AGC part of the first frame, i.e. start bit 1 and 2. */ if (decodedIRData.rawlen == 6) { - if ((matchMark(irparams.rawbuf[3], BEO_IR_MARK_FOR_DECODE) - || matchMark(irparams.rawbuf[3], BEO_DATALINK_MARK)) + 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")); + TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected")); } else { return false; // no B&O protocol } @@ -345,9 +333,9 @@ bool IRrecv::decodeBangOlufsen() { * Check if leading gap is trailing bit of first AGC frame */ if (!matchSpace(decodedIRData.initialGapTicks, BEO_PULSE_LENGTH_START_BIT)) { - 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 + TRACE_PRINT(F("B&O: Leading gap of ")); // Leading gap is trailing bit of first frame + TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); // Leading gap is trailing bit of first frame + TRACE_PRINTLN(F(" us is wrong")); // Leading gap is trailing bit of first frame return false; // no B&O protocol } @@ -358,7 +346,7 @@ bool IRrecv::decodeBangOlufsen() { protocolMarkLength = BEO_DATALINK_MARK; # endif } else { - BEO_TRACE_PRINTLN(F("B&O: mark length is wrong")); + TRACE_PRINTLN(F("B&O: mark length is wrong")); return false; } @@ -371,14 +359,14 @@ bool IRrecv::decodeBangOlufsen() { uint16_t markLength = irparams.rawbuf[tRawBufferMarkIndex]; uint16_t spaceLength = irparams.rawbuf[tRawBufferMarkIndex + 1]; - BEO_TRACE_PRINT(tPulseNumber); - BEO_TRACE_PRINT(' '); - BEO_TRACE_PRINT(markLength * MICROS_PER_TICK); - BEO_TRACE_PRINT(' '); - BEO_TRACE_PRINT(spaceLength * MICROS_PER_TICK); - BEO_TRACE_PRINT(F(" (")); - BEO_TRACE_PRINT((markLength + spaceLength) * MICROS_PER_TICK); - BEO_TRACE_PRINTLN(F(") ")); + TRACE_PRINT(tPulseNumber); + TRACE_PRINT(' '); + TRACE_PRINT(markLength * MICROS_PER_TICK); + TRACE_PRINT(' '); + TRACE_PRINT(spaceLength * MICROS_PER_TICK); + TRACE_PRINT(F(" (")); + TRACE_PRINT((markLength + spaceLength) * MICROS_PER_TICK); + TRACE_PRINTLN(F(") ")); #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP) /* @@ -389,7 +377,7 @@ bool IRrecv::decodeBangOlufsen() { if (tPulseNumber < 2) { // bit 0 and 1 if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK_FOR_DECODE)) { - BEO_TRACE_PRINTLN(F(": detected long start bit -> synchronize state now")); + TRACE_PRINTLN(F(": detected long start bit -> synchronize state now")); tPulseNumber = 2; } } else { @@ -401,14 +389,14 @@ bool IRrecv::decodeBangOlufsen() { protocolMarkLength = BEO_DATALINK_MARK; # endif } else { - BEO_DEBUG_PRINTLN(F("B&O: 4. (start) mark length is wrong")); + 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_PRINTLN(F("B&O: Start length is wrong")); + DEBUG_PRINTLN(F("B&O: Start length is wrong")); return false; } } @@ -424,7 +412,7 @@ bool IRrecv::decodeBangOlufsen() { #else if (!matchMark(markLength, BEO_IR_MARK_FOR_DECODE)) { #endif - BEO_DEBUG_PRINTLN(F("B&O: Mark length is wrong")); + DEBUG_PRINTLN(F("B&O: Mark length is wrong")); return false; } @@ -433,12 +421,12 @@ bool IRrecv::decodeBangOlufsen() { */ if (tBitNumber > BEO_DATA_BITS + 4) { if (matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_TRAILING_BIT)) { - BEO_DEBUG_PRINTLN(F("B&O: Trailing bit detected")); + 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_PRINTLN(F("B&O: End of buffer, but no trailing bit detected")); + DEBUG_PRINTLN(F("B&O: End of buffer, but no trailing bit detected")); return false; } #endif @@ -452,22 +440,22 @@ 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(F("B&O: Index=")); - BEO_DEBUG_PRINT(tRawBufferMarkIndex); - BEO_DEBUG_PRINT(F(" Length ")); - BEO_DEBUG_PRINT((markLength + spaceLength) * MICROS_PER_TICK); - BEO_DEBUG_PRINTLN(F(" is wrong")); + DEBUG_PRINT(F("B&O: Index=")); + DEBUG_PRINT(tRawBufferMarkIndex); + DEBUG_PRINT(F(" Length ")); + DEBUG_PRINT((markLength + spaceLength) * MICROS_PER_TICK); + DEBUG_PRINTLN(F(" is wrong")); return false; } tDecodedRawData <<= 1; tDecodedRawData |= tLastDecodedBitValue; ++tBitNumber; - BEO_TRACE_PRINT(F("Bits ")); - BEO_TRACE_PRINT(tBitNumber); - BEO_TRACE_PRINT(F(" ")); - BEO_TRACE_PRINT(uint32_t(tDecodedRawData >> BEO_DATA_BITS), HEX); - BEO_TRACE_PRINT(F(" ")); - BEO_TRACE_PRINTLN(uint8_t(tDecodedRawData & ((1 << BEO_DATA_BITS) - 1)), HEX); + TRACE_PRINT(F("Bits ")); + TRACE_PRINT(tBitNumber); + TRACE_PRINT(F(" ")); + TRACE_PRINT(uint32_t(tDecodedRawData >> BEO_DATA_BITS), HEX); + TRACE_PRINT(F(" ")); + TRACE_PRINTLN(uint8_t(tDecodedRawData & ((1 << BEO_DATA_BITS) - 1)), HEX); // End of bit decode #if !defined(ENABLE_BEO_WITHOUT_FRAME_GAP) } @@ -477,7 +465,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_PRINTLN(F("B&O: Last bit reached")); + TRACE_PRINTLN(F("B&O: Last bit reached")); break; } #endif @@ -488,14 +476,26 @@ bool IRrecv::decodeBangOlufsen() { } #endif - decodedIRData.protocol = BANG_OLUFSEN; - decodedIRData.address = tDecodedRawData >> BEO_DATA_BITS; // lower header tBitNumber - decodedIRData.command = tDecodedRawData & ((1 << BEO_DATA_BITS) - 1); // lower 8 tBitNumber - decodedIRData.extra = tDecodedRawData >> (BEO_DATA_BITS + 16); // upper header tBitNumber - decodedIRData.numberOfBits = tBitNumber; - decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; + LongUnion tValue; + tValue.ULong = tDecodedRawData; decodedIRData.decodedRawData = tDecodedRawData; + decodedIRData.numberOfBits = tBitNumber; + + decodedIRData.protocol = BANG_OLUFSEN; + decodedIRData.command = tValue.UByte.LowByte; + tValue.ULong = tValue.ULong >> BEO_DATA_BITS; + decodedIRData.address = tValue.UWord.LowWord; + if (tBitNumber > 24) { // 24 = 8 bit command and 16 bit address + decodedIRData.extra = tValue.UByte.MidHighByte; + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO; + } else { + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; + } return true; } + +/** @}*/ +#include "LocalDebugLevelEnd.h" + #endif // _IR_BANG_OLUFSEN_HPP diff --git a/src/ir_BoseWave.hpp b/src/ir_BoseWave.hpp index b278d1f0c..0118273b7 100644 --- a/src/ir_BoseWave.hpp +++ b/src/ir_BoseWave.hpp @@ -9,11 +9,9 @@ #ifndef _IR_BOSEWAVE_HPP #define _IR_BOSEWAVE_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -69,10 +67,9 @@ bool IRrecv::decodeBoseWave() { // Check we have enough data +4 for initial gap, start bit mark and space + stop bit mark if (decodedIRData.rawlen != (2 * BOSEWAVE_BITS) + 4) { - IR_DEBUG_PRINT(F("Bose: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 36")); + DEBUG_PRINT(F("Bose: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 36")); return false; } @@ -80,10 +77,7 @@ bool IRrecv::decodeBoseWave() { // Stop bit 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")); -#endif + DEBUG_PRINTLN(F("Bose: Stop bit mark length is wrong")); return false; } @@ -94,10 +88,7 @@ bool IRrecv::decodeBoseWave() { uint8_t tCommandInverted = tDecodedValue >> 8; // parity check for command. Use this variant to avoid compiler warning "comparison of promoted ~unsigned with unsigned [-Wsign-compare]" if ((tCommandNotInverted ^ tCommandInverted) != 0xFF) { -#if defined(LOCAL_DEBUG) - Serial.print(F("Bose: ")); - Serial.println(F("Command and inverted command check failed")); -#endif + DEBUG_PRINTLN(F("Bose: Command and inverted command check failed")); return false; } decodedIRData.command = tCommandNotInverted; @@ -111,7 +102,6 @@ bool IRrecv::decodeBoseWave() { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_BOSEWAVE_HPP diff --git a/src/ir_Denon.hpp b/src/ir_Denon.hpp index 69827fefb..ec1a3324d 100644 --- a/src/ir_Denon.hpp +++ b/src/ir_Denon.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2023 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,11 +32,9 @@ #ifndef _IR_DENON_HPP #define _IR_DENON_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -171,25 +169,22 @@ bool IRrecv::decodeDenon() { // we have no start bit, so check for the exact amount of data bits // Check we have the right amount of data (32). The + 2 is for initial gap + stop bit mark if (decodedIRData.rawlen != (2 * DENON_BITS) + 2) { - IR_DEBUG_PRINT(F("Denon: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 32")); + DEBUG_PRINT(F("Denon: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 32")); return false; } - // Try to decode as Denon protocol - decodePulseDistanceWidthData_P(&DenonProtocolConstants, DENON_BITS, 1); - - // 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")); -#endif + // Check for first mark, which is no AGC or start bit. This prevents Sony15 from being decoded as Denon. + // matchMark is too sensitive! + if (irparams.rawbuf[1] >= ((2 * DENON_HEADER_MARK) / MICROS_PER_TICK)) { + DEBUG_PRINTLN(F("Denon: First mark length is wrong")); return false; } + // Try to decode as Denon protocol + decodePulseDistanceWidthData_P(&DenonProtocolConstants, DENON_BITS, 1); + // Success decodedIRData.address = decodedIRData.decodedRawData & 0x1F; decodedIRData.command = decodedIRData.decodedRawData >> DENON_ADDRESS_BITS; @@ -214,21 +209,19 @@ bool IRrecv::decodeDenon() { /* * 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: Inverted frame")); -#endif + DEBUG_PRINTLN(F("Denon: Inverted frame")); + 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: Parity check of inverted with non inverted frame failed. Last command=")); - Serial.print((uint8_t)lastDecodedCommand, HEX); - Serial.print(F(" current=")); - Serial.println((uint8_t)~decodedIRData.command, HEX); -#endif + + DEBUG_PRINT(F("Denon: Parity check of inverted with non inverted frame failed. Last command=")); + DEBUG_PRINT((uint8_t )lastDecodedCommand, HEX); + DEBUG_PRINT(F(" current=")); + DEBUG_PRINTLN((uint8_t )~decodedIRData.command, HEX); } // always take non inverted command decodedIRData.command = lastDecodedCommand; @@ -269,8 +262,8 @@ void IRsend::sendDenon(unsigned long data, int nbits) { // Set IR carrier frequency enableIROut (DENON_KHZ); #if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) -// Serial.println( -// "The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats)."); + DEBUG_PRINTLN( + "The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats)."); #endif // Header @@ -317,7 +310,6 @@ bool IRrecv::decodeDenonOld(decode_results *aResults) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_DENON_HPP diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index 52fbf45f3..d0ea64ad7 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -62,15 +62,18 @@ #ifndef _IR_DISTANCE_WIDTH_HPP #define _IR_DISTANCE_WIDTH_HPP +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" + +/** \addtogroup Decoder Decoders and encoders for different protocols + * @{ + */ + #if !defined(DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS) #define DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS 100000 // 100 ms, bit it is just a guess #endif -#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) @@ -84,9 +87,6 @@ // Switch the decoding according to your needs //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // If active, it resembles LG, otherwise LSB first as most other protocols e.g. NEC and Kaseikyo/Panasonic -/** \addtogroup Decoder Decoders and encoders for different protocols - * @{ - */ //===================================================================================== // DDD III SSS TTTTTT AA N N CCC EEEE W W III DDD TTTTTT H H // D D I S TT A A NN N C E W W I D D TT H H @@ -243,8 +243,7 @@ bool IRrecv::decodeDistanceWidth() { } } else { #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS) - Serial.print(F("PULSE_DISTANCE_WIDTH: ")); - Serial.print(F("Mark ")); + Serial.print(F("PULSE_DISTANCE_WIDTH: Mark ")); Serial.print(tDurationTicks * MICROS_PER_TICK); Serial.print(F(" is longer than maximum ")); Serial.print(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE * MICROS_PER_TICK); @@ -268,8 +267,7 @@ bool IRrecv::decodeDistanceWidth() { if (!tSuccess) { #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")); + Serial.println(F("PULSE_DISTANCE_WIDTH: Mark aggregation failed, more than 2 distinct mark duration values found")); #endif return false; } @@ -290,8 +288,7 @@ bool IRrecv::decodeDistanceWidth() { } } else { #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS) - Serial.print(F("PULSE_DISTANCE_WIDTH: ")); - Serial.print(F("Space ")); + Serial.print(F("PULSE_DISTANCE_WIDTH: Space ")); Serial.print(tDurationTicks * MICROS_PER_TICK); Serial.print(F(" is longer than maximum ")); Serial.print(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE * MICROS_PER_TICK); @@ -315,8 +312,7 @@ bool IRrecv::decodeDistanceWidth() { if (!tSuccess) { #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")); + Serial.println(F("PULSE_DISTANCE_WIDTH: Space aggregation failed, more than 2 distinct space duration values found")); #endif return false; } @@ -381,10 +377,8 @@ bool IRrecv::decodeDistanceWidth() { */ if (tMarkTicksLong == 0 && tSpaceTicksLong == 0) { -#if defined(LOCAL_DEBUG) - Serial.print(F("PULSE_DISTANCE: ")); - Serial.println(F("Cannot decode, because there is only one distinct duration value for each space and mark")); -#endif + DEBUG_PRINTLN( + F("PULSE_DISTANCE: Cannot decode, because there is only one distinct duration value for each space and mark")); return false; } unsigned int tSpaceMicrosShort; @@ -410,7 +404,7 @@ bool IRrecv::decodeDistanceWidth() { if (tSpaceTicksLong > 0) { /* * 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 :-). + * PULSE_DISTANCE_WIDTH can be successfully decoded by only using the timings of space :-). */ decodedIRData.protocol = PULSE_DISTANCE; // NEC etc. + PULSE_DISTANCE_WIDTH #if defined(USE_THRESHOLD_DECODER) @@ -449,11 +443,15 @@ bool IRrecv::decodeDistanceWidth() { ); } + DEBUG_PRINT(F("PULSE_WIDTH: decodedRawData=0x")); #if defined(LOCAL_DEBUG) - Serial.print(F("PULSE_WIDTH: ")); - Serial.print(F("decodedRawData=0x")); +# if (__INT_WIDTH__ < 32) Serial.println(decodedIRData.decodedRawData, HEX); +# else + PrintULL::println(&Serial, decodedIRData.decodedRawData, HEX); +# endif #endif + // fill array with decoded data decodedIRData.decodedRawDataArray[i] = decodedIRData.decodedRawData; tStartIndex += (2 * BITS_IN_RAW_DATA_TYPE); @@ -510,7 +508,6 @@ bool IRrecv::decodeDistanceWidth() { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_DISTANCE_WIDTH_HPP diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index 81c7281a3..89cef8f4b 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -35,11 +35,9 @@ #include "TinyIR.h" -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -101,10 +99,9 @@ bool IRrecv::decodeFAST() { // Check we have the right amount of data (36). The +4 is for initial gap, start bit mark and space + stop bit mark. if (decodedIRData.rawlen != ((2 * FAST_BITS) + 4)) { - IR_DEBUG_PRINT(F("FAST: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 36")); + DEBUG_PRINT(F("FAST: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 36")); return false; } @@ -117,15 +114,13 @@ bool IRrecv::decodeFAST() { tValue.UWord = decodedIRData.decodedRawData; 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(F(" received=0x")); - Serial.print(tValue.UByte.HighByte, HEX); - Serial.print(F(" data=0x")); - Serial.println(tValue.UWord, HEX); -#endif + DEBUG_PRINT(F("FAST: 8 bit parity is not correct. Expected=0x")); + DEBUG_PRINT((uint8_t) ~(tValue.UByte.LowByte), HEX); + DEBUG_PRINT(F(" received=0x")); + DEBUG_PRINT(tValue.UByte.HighByte, HEX); + DEBUG_PRINT(F(" data=0x")); + DEBUG_PRINTLN(tValue.UWord, HEX); + decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED; } @@ -142,7 +137,6 @@ bool IRrecv::decodeFAST() { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_FAST_HPP diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index 500b91641..d5276d2af 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -32,11 +32,7 @@ #ifndef _IR_JVC_HPP #define _IR_JVC_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -124,10 +120,9 @@ bool IRrecv::decodeJVC() { // Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark. // +4 is for first frame, +2 is for repeats if (decodedIRData.rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawlen != ((2 * JVC_BITS) + 4)) { - IR_DEBUG_PRINT(F("JVC: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 34 or 36")); + DEBUG_PRINT(F("JVC: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 34 or 36")); return false; } @@ -189,9 +184,9 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) { // Check we have enough data - +3 for start bit mark and space + stop bit mark if (aResults->rawlen <= (2 * JVC_BITS) + 3) { - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(aResults->rawlen); - IR_DEBUG_PRINTLN(F(" is too small. >= 36 is required.")); + DEBUG_PRINT(F("Data length=")); + DEBUG_PRINT(aResults->rawlen); + DEBUG_PRINTLN(F(" is too small. >= 36 is required.")); return false; } @@ -205,9 +200,7 @@ bool IRrecv::decodeJVCMSB(decode_results *aResults) { // Stop bit if (!matchMark(aResults->rawbuf[offset + (2 * JVC_BITS)], JVC_BIT_MARK)) { -#if defined(LOCAL_DEBUG) - Serial.println(F("Stop bit mark length is wrong")); -#endif + DEBUG_PRINTLN(F("Stop bit mark length is wrong")); return false; } @@ -246,7 +239,6 @@ void IRsend::sendJVCMSB(unsigned long data, int nbits, bool repeat) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_JVC_HPP diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index fa1086851..3e0fb3c86 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -32,11 +32,9 @@ #ifndef _IR_KASEIKYO_HPP #define _IR_KASEIKYO_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -201,10 +199,9 @@ bool IRrecv::decodeKaseikyo() { decode_type_t tProtocol; // Check we have enough data (96 + 4) 4 for initial gap, start bit mark and space + stop bit mark if (decodedIRData.rawlen != ((2 * KASEIKYO_BITS) + 4)) { - IR_DEBUG_PRINT(F("Kaseikyo: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 100")); + DEBUG_PRINT(F("Kaseikyo: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 100")); return false; } @@ -256,15 +253,12 @@ bool IRrecv::decodeKaseikyo() { if (tVendorParity != (tValue.UByte.LowByte & 0xF)) { decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_LSB_FIRST; -#if defined(LOCAL_DEBUG) - Serial.print(F("Kaseikyo: ")); - Serial.print(F("4 bit VendorID parity is not correct. Expected=0x")); - Serial.print(tVendorParity, HEX); - Serial.print(F(" received=0x")); - Serial.print(decodedIRData.decodedRawData, HEX); - Serial.print(F(" VendorID=0x")); - Serial.println(tVendorId, HEX); -#endif + DEBUG_PRINT(F("Kaseikyo: 4 bit VendorID parity is not correct. Expected=0x")); + DEBUG_PRINT(tVendorParity, HEX); + DEBUG_PRINT(F(" received=0x")); + DEBUG_PRINT(decodedIRData.decodedRawData, HEX); + DEBUG_PRINT(F(" VendorID=0x")); + DEBUG_PRINTLN(tVendorId, HEX); } if (tProtocol == KASEIKYO) { @@ -275,17 +269,14 @@ bool IRrecv::decodeKaseikyo() { if (tValue.UByte.HighByte != tParity) { decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED; -#if defined(LOCAL_DEBUG) - Serial.print(F("Kaseikyo: ")); - Serial.print(F("8 bit parity is not correct. Expected=0x")); - Serial.print(tParity, HEX); - Serial.print(F(" received=0x")); - Serial.print(decodedIRData.decodedRawData >> KASEIKYO_COMMAND_BITS, HEX); - Serial.print(F(" address=0x")); - Serial.print(decodedIRData.address, HEX); - Serial.print(F(" command=0x")); - Serial.println(decodedIRData.command, HEX); -#endif + DEBUG_PRINT(F("Kaseikyo: 8 bit parity is not correct. Expected=0x")); + DEBUG_PRINT(tParity, HEX); + DEBUG_PRINT(F(" received=0x")); + DEBUG_PRINT(decodedIRData.decodedRawData >> KASEIKYO_COMMAND_BITS, HEX); + DEBUG_PRINT(F(" address=0x")); + DEBUG_PRINT(decodedIRData.address, HEX); + DEBUG_PRINT(F(" command=0x")); + DEBUG_PRINTLN(decodedIRData.command, HEX); } decodedIRData.numberOfBits = KASEIKYO_BITS; @@ -304,7 +295,6 @@ bool IRrecv::decodeKaseikyo() { */ /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_KASEIKYO_HPP diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 28c04c654..12724b04c 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -32,11 +32,7 @@ #ifndef _IR_LG_HPP #define _IR_LG_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -186,10 +182,9 @@ 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); - IR_DEBUG_PRINTLN(F(" is not 60 or 4")); + DEBUG_PRINT(F("LG: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 60 or 4")); return false; } @@ -199,10 +194,7 @@ bool IRrecv::decodeLG() { tProtocol = LG2; tHeaderSpace = LG2_HEADER_SPACE; } else { -#if defined(LOCAL_DEBUG) - Serial.print(F("LG: ")); - Serial.println(F("Header mark is wrong")); -#endif + DEBUG_PRINTLN(F("LG: Header mark is wrong")); return false; // neither LG nor LG2 header } } @@ -216,19 +208,13 @@ bool IRrecv::decodeLG() { decodedIRData.protocol = lastDecodedProtocol; return true; } -#if defined(LOCAL_DEBUG) - Serial.print(F("LG: ")); - Serial.print(F("Repeat header space is wrong")); -#endif + DEBUG_PRINTLN(F("LG: Repeat header space is wrong")); return false; } // Check command header space if (!matchSpace(irparams.rawbuf[2], tHeaderSpace)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("LG: ")); - Serial.println(F("Header space length is wrong")); -#endif + DEBUG_PRINTLN(F("LG: Header space length is wrong")); return false; } @@ -250,15 +236,14 @@ bool IRrecv::decodeLG() { } // Checksum check if ((tChecksum & 0xF) != (decodedIRData.decodedRawData & 0xF)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("LG: ")); - Serial.print(F("4 bit checksum is not correct. expected=0x")); - Serial.print(tChecksum, HEX); - Serial.print(F(" received=0x")); - Serial.print((decodedIRData.decodedRawData & 0xF), HEX); - Serial.print(F(" data=0x")); - Serial.println(decodedIRData.command, HEX); -#endif + + DEBUG_PRINT(F("LG: 4 bit checksum is not correct. expected=0x")); + DEBUG_PRINT(tChecksum, HEX); + DEBUG_PRINT(F(" received=0x")); + DEBUG_PRINT((decodedIRData.decodedRawData & 0xF), HEX); + DEBUG_PRINT(F(" data=0x")); + DEBUG_PRINTLN(decodedIRData.command, HEX); + decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED; } @@ -304,9 +289,7 @@ bool IRrecv::decodeLGMSB(decode_results *aResults) { // Stop bit if (!matchMark(aResults->rawbuf[offset + (2 * LG_BITS)], LG_BIT_MARK)) { -#if defined(LOCAL_DEBUG) - Serial.println(F("Stop bit mark length is wrong")); -#endif + DEBUG_PRINTLN(F("Stop bit mark length is wrong")); return false; } @@ -323,20 +306,18 @@ void IRsend::sendLG(unsigned long data, int nbits) { // Set IR carrier frequency enableIROut (LG_KHZ); #if !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) -// Serial.println(F( -// "The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).")); + DEBUG_PRINTLN( + F( "The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).")); #endif // Header mark(LG_HEADER_MARK); space(LG_HEADER_SPACE); -// mark(LG_BIT_MARK); // Data + stop bit sendPulseDistanceWidthData(LG_BIT_MARK, LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, data, nbits, PROTOCOL_IS_MSB_FIRST); } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_LG_HPP diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 1104395da..506f174eb 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -32,11 +32,7 @@ #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 +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -127,10 +123,8 @@ void IRsend::sendLegoPowerFunctions(uint8_t aChannel, uint8_t aCommand, uint8_t void IRsend::sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times) { -#if defined(LOCAL_DEBUG) - Serial.print(F("sendLego aRawData=0x")); - Serial.println(aRawData, HEX); -#endif + DEBUG_PRINT(F("sendLego aRawData=0x")); + DEBUG_PRINTLN(aRawData, HEX); aChannel &= 0x03; // we have 4 channels @@ -159,10 +153,9 @@ bool IRrecv::decodeLegoPowerFunctions() { // Check we have enough data - +4 for initial gap, start bit mark and space + stop bit mark if (decodedIRData.rawlen != (2 * LEGO_BITS) + 4) { - IR_DEBUG_PRINT(F("LEGO: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(irparams.rawlen); - IR_DEBUG_PRINTLN(F(" is not 36")); + DEBUG_PRINT(F("LEGO: Data length=")); + DEBUG_PRINT(irparams.rawlen); + DEBUG_PRINTLN(F(" is not 36")); return false; } @@ -170,10 +163,8 @@ bool IRrecv::decodeLegoPowerFunctions() { // 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 +// DEBUG_PRINT(F("LEGO: ")); +// DEBUG_PRINTLN(F("Stop bit mark length is wrong")); // return false; // } @@ -191,21 +182,18 @@ bool IRrecv::decodeLegoPowerFunctions() { // parity check if (tParityReceived != tParityComputed) { -#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 + DEBUG_PRINT(F("LEGO: Parity is not correct. expected=0x")); + DEBUG_PRINT(tParityComputed, HEX); + DEBUG_PRINT(F(" received=0x")); + DEBUG_PRINT(tParityReceived, HEX); + DEBUG_PRINT(F(", raw=0x")); + DEBUG_PRINT(tDecodedValue, HEX); + DEBUG_PRINT(F(", 3 nibbles are 0x")); + DEBUG_PRINT(tToggleEscapeChannel, HEX); + DEBUG_PRINT(F(", 0x")); + DEBUG_PRINT(tMode, HEX); + DEBUG_PRINT(F(", 0x")); + DEBUG_PRINTLN(tData, HEX); // might not be an error, so just continue decodedIRData.flags = IRDATA_FLAGS_PARITY_FAILED | IRDATA_FLAGS_IS_MSB_FIRST; } @@ -233,7 +221,6 @@ void IRsend::sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_LEGO_HPP diff --git a/src/ir_MagiQuest.hpp b/src/ir_MagiQuest.hpp index 3517fb694..27e75251e 100644 --- a/src/ir_MagiQuest.hpp +++ b/src/ir_MagiQuest.hpp @@ -38,11 +38,13 @@ #ifndef _IR_MAGIQUEST_HPP #define _IR_MAGIQUEST_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" + +/** \addtogroup Decoder Decoders and encoders for different protocols + * @{ + */ // //============================================================================== // @@ -137,11 +139,10 @@ void IRsend::sendMagiQuest(uint32_t aWandId, uint16_t aMagnitude) { 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")); - Serial.println(tChecksum, HEX); -#endif + DEBUG_PRINT(F("MagiQuest checksum=0x")); + DEBUG_PRINTLN(tChecksum, HEX); } //+============================================================================= @@ -156,10 +157,9 @@ bool IRrecv::decodeMagiQuest() { // Check we have the right amount of data, magnitude and ID bits and 8 start bits + 0 stop bit if (decodedIRData.rawlen != (2 * MAGIQUEST_BITS)) { - IR_DEBUG_PRINT(F("MagiQuest: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 112")); + DEBUG_PRINT(F("MagiQuest: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 112")); return false; } @@ -173,11 +173,8 @@ bool IRrecv::decodeMagiQuest() { if (decodedIRData.decodedRawData != 0) #endif { -#if defined(LOCAL_DEBUG) - Serial.print(F("MagiQuest: ")); - Serial.print(F("Not 8 leading zero start bits received, RawData=0x")); - Serial.println(decodedIRData.decodedRawData, HEX); -#endif + DEBUG_PRINT(F("MagiQuest: Not 8 leading zero start bits received, RawData=0x")); + DEBUG_PRINTLN(decodedIRData.decodedRawData, HEX); return false; } @@ -193,12 +190,12 @@ bool IRrecv::decodeMagiQuest() { 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]; -#if defined(LOCAL_DEBUG) - Serial.print(F("31 bit WandId=0x")); - Serial.print(decodedIRData.decodedRawData, HEX); - Serial.print(F(" shifted=0x")); - Serial.println(tDecodedRawData.ULong, HEX); -#endif + + DEBUG_PRINT(F("31 bit WandId=0x")); + DEBUG_PRINT(decodedIRData.decodedRawData, HEX); + DEBUG_PRINT(F(" shifted=0x")); + DEBUG_PRINTLN(tDecodedRawData.ULong, HEX); + /* * Decode the 9 bit Magnitude + 8 bit checksum */ @@ -210,21 +207,18 @@ bool IRrecv::decodeMagiQuest() { #endif -#if defined(LOCAL_DEBUG) - Serial.print(F("Magnitude + checksum=0x")); - Serial.println(decodedIRData.decodedRawData, HEX); -#endif + DEBUG_PRINT(F("Magnitude + checksum=0x")); + DEBUG_PRINTLN(decodedIRData.decodedRawData, HEX); + tDecodedRawData.ULong = decodedIRData.decodedRawData; decodedIRData.command = tDecodedRawData.UBytes[1] | tDecodedRawData.UBytes[2] << 8; // Values observed are 0x102,01,04,37,05,38,2D| 02,06,04|03,103,12,18,0E|09 tChecksum += tDecodedRawData.UBytes[2] /* only one bit */+ tDecodedRawData.UBytes[1] + tDecodedRawData.UBytes[0]; if (tChecksum != 0) { decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED; -#if defined(LOCAL_DEBUG) - Serial.print(F("Checksum 0x")); - Serial.print(tChecksum, HEX); - Serial.println(F(" is not 0")); -#endif + DEBUG_PRINT(F("Checksum 0x")); + DEBUG_PRINT(tChecksum, HEX); + DEBUG_PRINTLN(F(" is not 0")); } // Success @@ -238,7 +232,8 @@ bool IRrecv::decodeMagiQuest() { return true; } -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif + +/** @}*/ +#include "LocalDebugLevelEnd.h" + #endif // _IR_MAGIQUEST_HPP diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index e70c87c88..79c8809e3 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -32,11 +32,9 @@ #ifndef _IR_NEC_HPP #define _IR_NEC_HPP -#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. -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -242,10 +240,9 @@ bool IRrecv::decodeNEC() { */ // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. if (decodedIRData.rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawlen != 4)) { - IR_DEBUG_PRINT(F("NEC: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 68 or 4")); + DEBUG_PRINT(F("NEC: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 68 or 4")); return false; } @@ -269,10 +266,7 @@ bool IRrecv::decodeNEC() { // Check command header space if (!matchSpace(irparams.rawbuf[2], NEC_HEADER_SPACE)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("NEC: ")); - Serial.println(F("Header space length is wrong")); -#endif + DEBUG_PRINTLN(F("NEC: Header space length is wrong")); return false; } @@ -356,19 +350,15 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) { // Check we have the right amount of data (32). +4 for initial gap, start bit mark and space + stop bit mark if (aResults->rawlen != (2 * NEC_BITS) + 4) { - IR_DEBUG_PRINT(F("NEC MSB: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(aResults->rawlen); - IR_DEBUG_PRINTLN(F(" is not 68")); + DEBUG_PRINT(F("NEC MSB: Data length=")); + DEBUG_PRINT(aResults->rawlen); + DEBUG_PRINTLN(F(" is not 68")); return false; } // Check header "space" if (!matchSpace(aResults->rawbuf[offset], NEC_HEADER_SPACE)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("NEC MSB: ")); - Serial.println(F("Header space length is wrong")); -#endif + DEBUG_PRINTLN(F("NEC MSB: Header space length is wrong")); return false; } offset++; @@ -377,10 +367,7 @@ bool IRrecv::decodeNECMSB(decode_results *aResults) { // Stop bit if (!matchMark(aResults->rawbuf[offset + (2 * NEC_BITS)], NEC_BIT_MARK)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("NEC MSB: ")); - Serial.println(F("Stop bit mark length is wrong")); -#endif + DEBUG_PRINTLN(F("NEC MSB: Stop bit mark length is wrong")); return false; } @@ -422,7 +409,6 @@ void IRsend::sendNECMSB(uint32_t data, uint8_t nbits, bool repeat) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_NEC_HPP diff --git a/src/ir_OpenLASIR.hpp b/src/ir_OpenLASIR.hpp index 125e3d04c..bceecc0a1 100644 --- a/src/ir_OpenLASIR.hpp +++ b/src/ir_OpenLASIR.hpp @@ -46,11 +46,9 @@ #ifndef _IR_OPENLASIR_HPP #define _IR_OPENLASIR_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -237,10 +235,9 @@ bool IRrecv::decodeOpenLASIR() { // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. if (decodedIRData.rawlen != ((2 * OPENLASIR_BITS) + 4) && (decodedIRData.rawlen != 4)) { - IR_DEBUG_PRINT(F("OpenLASIR: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 68 or 4")); + DEBUG_PRINT(F("OpenLASIR: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 68 or 4")); return false; } @@ -265,10 +262,7 @@ bool IRrecv::decodeOpenLASIR() { // Check command header space if (!matchSpace(irparams.rawbuf[2], NEC_HEADER_SPACE)) { -#if defined(LOCAL_DEBUG) - Serial.print(F("OpenLASIR: ")); - Serial.println(F("Header space length is wrong")); -#endif + DEBUG_PRINTLN(F("OpenLASIR: Header space length is wrong")); return false; } @@ -282,8 +276,7 @@ bool IRrecv::decodeOpenLASIR() { // Validate address: second byte must be inverted first byte if (tValue.UByte.LowByte != (uint8_t)(~tValue.UByte.MidLowByte)) { // Address validation failed - this is not a valid OpenLASIR frame - IR_DEBUG_PRINT(F("OpenLASIR: ")); - IR_DEBUG_PRINTLN(F("Address validation failed")); + DEBUG_PRINTLN(F("OpenLASIR: Address validation failed")); return false; } @@ -297,8 +290,7 @@ bool IRrecv::decodeOpenLASIR() { * with NEC devices except in very rare cases of collisions.") */ if (tValue.UByte.MidHighByte == (uint8_t)(~tValue.UByte.HighByte)) { - IR_DEBUG_PRINT(F("OpenLASIR: ")); - IR_DEBUG_PRINTLN(F("Command has valid inverse - looks like standard NEC, skipping")); + DEBUG_PRINTLN(F("OpenLASIR: Command has valid inverse - looks like standard NEC, skipping")); return false; } @@ -315,7 +307,6 @@ bool IRrecv::decodeOpenLASIR() { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_OPENLASIR_HPP diff --git a/src/ir_Pronto.hpp b/src/ir_Pronto.hpp index 4ad198500..c4723a168 100644 --- a/src/ir_Pronto.hpp +++ b/src/ir_Pronto.hpp @@ -36,11 +36,7 @@ #ifndef _IR_PRONTO_HPP #define _IR_PRONTO_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -84,12 +80,12 @@ void IRsend::sendPronto(const uint16_t *data, uint16_t length, int_fast8_t aNumb } uint16_t intros = 2 * data[2]; uint16_t repeats = 2 * data[3]; -#if defined(LOCAL_DEBUG) - Serial.print(F("sendPronto intros=")); - Serial.print(intros); - Serial.print(F(" repeats=")); - Serial.println(repeats); -#endif + + DEBUG_PRINT(F("sendPronto intros=")); + DEBUG_PRINT(intros); + DEBUG_PRINT(F(" repeats=")); + DEBUG_PRINTLN(repeats); + if (numbersInPreamble + intros + repeats != length) { // inconsistent sizes return; } @@ -255,7 +251,7 @@ static void compensateAndDumpSequence(Print *aSerial, const volatile IRRawbufTyp * Print the result (second argument) as Pronto Hex on the Print supplied as argument. * Used in the ReceiveDump example. * Do not print repeat sequence data. - * @param aSerial The Print object on which to write, for Arduino you can use &Serial. + * @param aSerial The Print object on which to write, you can use &Serial for Arduino. * @param aFrequencyHertz Modulation frequency in Hz. Often 38000Hz. */ void IRrecv::compensateAndPrintIRResultAsPronto(Print *aSerial, uint16_t aFrequencyHertz) { @@ -341,7 +337,6 @@ size_t IRrecv::compensateAndStorePronto(String *aString, uint16_t frequency) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_PRONTO_HPP diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index f26478d6c..61369232c 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -32,17 +32,15 @@ #ifndef _IR_RC5_RC6_HPP #define _IR_RC5_RC6_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +// This block must be located after the includes of other *.hpp files +//#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ */ -uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 -//uint8_t sLastReceiveToggleValue = 3; // 3 -> start value +uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only required for biphase protocols. //============================================================================== // RRRR CCCC 55555 @@ -52,20 +50,28 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 // R R CCCC 5555 //============================================================================== /* - Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first - + 900,- 900 - +1800,-1750 +1800,- 850 + 900,- 850 + 900,-1750 - + 950,- 850 + 900,- 850 +1800,-1750 + 950,- 850 - +1800 - Sum: 23100 + Protocol=RC5 Address=0x11, Command=0x36, Raw-Data=0x1476, 13 bits, MSB first + + 950,- 850 + +1850,-1700 +1850,- 850 + 900,- 850 +1000,-1700 + + 950,- 850 + 950,- 800 +1850,-1750 + 950,- 850 + +1850 + Duration=23300us RC5X with 7.th MSB of command set as 1 - Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first - +1800,-1750 - + 850,- 900 +1800,- 850 + 950,- 850 + 900,-1750 - + 900,- 850 + 950,- 850 +1800,-1750 + 900,- 850 - +1800 - Sum: 23050 + Protocol=RC5 Address=0x11, Command=0x76, Toggle=1, Raw-Data=0xC76, 13 bits, MSB first + +1900,-1700 + + 950,- 850 +1850,- 800 + 950,- 800 +1000,-1700 + +1000,- 750 + 950,- 900 +1800,-1700 +1000,- 800 + +1850 + Duration=23250us + + Protocol=Marantz Address=0x11, Command=0x76, Extra=0x9, Toggle=1, Raw-Data=0x31D89, 19 bits, MSB first + +1850,-1700 + + 950,- 850 +1850,- 850 + 950,- 800 +1000,-1700 + + 950,-4350 + 950,- 900 +1850,-1700 + 900,- 850 + +1850,- 850 + 950,- 800 +1000,-1700 +1800,- 900 + + 900,-1750 + 950 + Duration=38400us */ // // see: https://www.sbprojects.net/knowledge/ir/rc5.php @@ -94,19 +100,18 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 #define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7 - Divided by 2 to handle the bit sequence of 01010101 which gives one mark and space for each 2 bits -#define RC5_DURATION (15 * RC5_UNIT) // 13335 +#define RC5_DURATION (26 * RC5_UNIT) // 23114 #define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792 -#define RC5_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - RC5_DURATION) // 100 ms -#define RC5_MAXIMUM_REPEAT_DISTANCE (RC5_REPEAT_DISTANCE + (RC5_REPEAT_DISTANCE / 4)) // Just a guess +#define RC5_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - RC5_DURATION) // 90 ms +#define RC5_MAXIMUM_REPEAT_DISTANCE (RC5_REPEAT_DISTANCE + (RC5_REPEAT_DISTANCE / 4)) // Just a guess #define MARANTZ_COMMAND_EXTENSION_BITS 6 #define MARANTZ_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS) // 19 #define MARANTZ_PAUSE_BIT_INDEX (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS) // 7 #define MARANTZ_PAUSE_DURATION (4 * RC5_UNIT) // 3556 -#define MARANTZ_DURATION (24 * RC5_UNIT) // RC5 + 6 Extension bits + 4 pause units = 22225 -#define MARANTZ_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - MARANTZ_DURATION) // 100 ms - +#define MARANTZ_DURATION (42L * RC5_UNIT) // RC5 + 6 Extension bits + 4 pause units = 37338 +#define MARANTZ_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - MARANTZ_DURATION) // 100 ms /************************************ * Start of send and decode functions @@ -122,7 +127,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0 * @param aMarantzExtension 6 bit command extension which is sent after 6 command bits of aCommand. aCommand and aMarantzExtension are sent after a short pause. * @param aEnableAutomaticToggle Send toggle bit according to the state of the static sLastSendToggleValue variable. */ -void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats,uint8_t aMarantzExtension, +void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aMarantzExtension, bool aEnableAutomaticToggle) { // Set IR carrier frequency @@ -226,18 +231,18 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe } } +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6) +void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) { + irparams.RawbuffOffsetForNextBiphaseLevel = aRCDecodeRawbuffOffset; + irparams.BiphaseTimeUnit = aBiphaseTimeUnit; + irparams.AlreadyUsedTimingIntervalsOfCurrentInterval = 0; +} + /* - * Static variables for the getBiphaselevel function + * Margin is 1/2 of unit. */ -uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array -uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing. -uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals. -uint16_t sBiphaseTimeUnit; - -void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) { - sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset; - sBiphaseTimeUnit = aBiphaseTimeUnit; - sBiphaseUsedTimingIntervals = 0; +uint8_t IRrecv::getNumberOfUnitsInInterval(uint16_t aCurrentInterval, uint16_t aTimeUnit) { + return (aCurrentInterval + (aTimeUnit / 2)) / aTimeUnit; } /** @@ -255,50 +260,54 @@ void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBip * 1 0 0 0 1 1 0 1 0 1 1 - Space * A mark to space at a significant clock edge results in a 1 * A space to mark at a significant clock edge results in a 0 - * Returns current level [MARK or SPACE] or NO_MARK_OR_SPACE for error (measured time interval is not a multiple of sBiphaseTimeUnit). + * Returns current level [MARK or SPACE] or NO_MARK_OR_SPACE for error (measured time interval is not a multiple of BiphaseTimeUnit). */ uint_fast8_t IRrecv::getBiphaselevel() { - uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK) + uint_fast8_t tLevelOfCurrentInterval; // Return value: 0 (SPACE) or 1 (MARK) - if (sBiphaseDecodeRawbuffOffset >= decodedIRData.rawlen) { + if (irparams.RawbuffOffsetForNextBiphaseLevel >= decodedIRData.rawlen) { return SPACE; // After end of recorded buffer, assume space. } - tLevelOfCurrentInterval = (sBiphaseDecodeRawbuffOffset) & 1; // on odd rawbuf offsets we have mark timings + tLevelOfCurrentInterval = (irparams.RawbuffOffsetForNextBiphaseLevel) & 1; // on odd rawbuf offsets we have mark timings /* - * Setup data if sUsedTimingIntervals is 0 + * Refill NumberOfTimingIntervalsInCurrentInterval if AlreadyUsedTimingIntervalsOfCurrentInterval is 0 + * i.e. we went to next rawbuf interval */ - if (sBiphaseUsedTimingIntervals == 0) { - uint16_t tCurrentTimingWith = irparams.rawbuf[sBiphaseDecodeRawbuffOffset]; - uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS; - - if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 1; - } else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 2; - } else if (matchTicks(tCurrentTimingWith, (3 * sBiphaseTimeUnit) + tMarkExcessCorrection)) { - sBiphaseCurrentTimingIntervals = 3; - } else { - return NO_MARK_OR_SPACE; - } + if (irparams.AlreadyUsedTimingIntervalsOfCurrentInterval == 0) { + uint16_t tCurrentIntervalWithMicros = irparams.rawbuf[irparams.RawbuffOffsetForNextBiphaseLevel] * MICROS_PER_TICK; + uint16_t tMarkExcessCorrectionMicros = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS; + irparams.NumberOfTimingIntervalsInCurrentInterval = getNumberOfUnitsInInterval( + tCurrentIntervalWithMicros + tMarkExcessCorrectionMicros, irparams.BiphaseTimeUnit); + // 666 is 3/4 of RC5 time unit + TRACE_PRINT(tLevelOfCurrentInterval); + TRACE_PRINT(F("=")); + TRACE_PRINT(tCurrentIntervalWithMicros + tMarkExcessCorrectionMicros); + TRACE_PRINT(F(" ")); + TRACE_PRINTLN(irparams.NumberOfTimingIntervalsInCurrentInterval); + } + if (irparams.NumberOfTimingIntervalsInCurrentInterval == 0) { + return NO_MARK_OR_SPACE; } // We use another interval from tCurrentTimingIntervals - sBiphaseUsedTimingIntervals++; + irparams.AlreadyUsedTimingIntervalsOfCurrentInterval++; -// keep track of current timing offset - if (sBiphaseUsedTimingIntervals >= sBiphaseCurrentTimingIntervals) { - // we have used all intervals of current timing, switch to next timing value - sBiphaseUsedTimingIntervals = 0; - sBiphaseDecodeRawbuffOffset++; + if (irparams.AlreadyUsedTimingIntervalsOfCurrentInterval >= irparams.NumberOfTimingIntervalsInCurrentInterval) { + /* + * We have used all intervals of current interval (mark or space duration in rawbuf), go to next rawbuf interval + */ + irparams.AlreadyUsedTimingIntervalsOfCurrentInterval = 0; + irparams.RawbuffOffsetForNextBiphaseLevel++; } - IR_TRACE_PRINTLN(tLevelOfCurrentInterval); return tLevelOfCurrentInterval; } +# endif // defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6) +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) /** * Try to decode data as RC5 protocol * mark->space => 0 @@ -324,17 +333,21 @@ bool IRrecv::decodeRC5() { // Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark. if (decodedIRData.rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawlen) { // no debug output, since this check is mainly to determine the received protocol - IR_DEBUG_PRINT(F("RC5: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not between 9 and 15")); + DEBUG_PRINT(F("RC5: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not between 9 and 15")); + return false; + } + + // Check length of first mark / header + if (irparams.rawbuf[1] > (((2 * RC5_UNIT) + (RC5_UNIT / 2)) / MICROS_PER_TICK)) { + DEBUG_PRINTLN(F("RC5: first MARK is too long")); return false; } -// Check start bit, the first space is included in the gap + // Check start bit, the first space is included in the gap if (getBiphaselevel() != MARK) { - IR_DEBUG_PRINT(F("RC5: ")); - IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK")); + DEBUG_PRINTLN(F("RC5: first getBiphaselevel() is not MARK")); return false; } @@ -344,7 +357,7 @@ bool IRrecv::decodeRC5() { #if defined(DECODE_MARANTZ) bool RC5Marantz = false; #endif - for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) { + for (tBitIndex = 0; irparams.RawbuffOffsetForNextBiphaseLevel < decodedIRData.rawlen; tBitIndex++) { // get next 2 levels and check for transition uint8_t tStartLevel = getBiphaselevel(); uint8_t tEndLevel = getBiphaselevel(); @@ -357,37 +370,36 @@ bool IRrecv::decodeRC5() { tDecodedRawData = (tDecodedRawData << 1) | 0; #if defined(DECODE_MARANTZ) } else if (tBitIndex == MARANTZ_PAUSE_BIT_INDEX) { - Serial.print(F("Off=")); - Serial.print(sBiphaseDecodeRawbuffOffset); - Serial.print(F(" ticks=")); - Serial.print(irparams.rawbuf[sBiphaseDecodeRawbuffOffset]); - Serial.print(F(" + ")); - Serial.print(irparams.rawbuf[sBiphaseDecodeRawbuffOffset + 1]); - Serial.println(); /* * Check for RC5 Marantz format i.e. long space after 8 bits (including start bit) * Check if timing buffer contains a pause, which is longer than 3/4 the expected pause + * Some dumb compiler throw a warning: comparison is always false due to limited range of data type [-Wtype-limits] which is nonsense */ - if (irparams.rawbuf[sBiphaseDecodeRawbuffOffset] > (((MARANTZ_PAUSE_DURATION * 3)/ MICROS_PER_TICK * 4))) { + if (irparams.rawbuf[irparams.RawbuffOffsetForNextBiphaseLevel] > ((MARANTZ_PAUSE_DURATION * 3L) / (MICROS_PER_TICK * 4L))) { // 3556 * 3 / 200 = 53 RC5Marantz = true; - // consume the long space - getBiphaselevel(); - getBiphaselevel(); - getBiphaselevel(); - getBiphaselevel(); + DEBUG_PRINTLN(F("Marantz detected")); + /* + * Here we are at the space interval and have 4 cases: + * With 0 -> mark+space and 1 -> space+mark and pause = 4*space we get the following space length + * 0 | pause | 0 -> 5*space + * 0 | pause | 1 -> 6*space + * 1 | pause | 0 -> 4*space + * 1 | pause | 1 -> 5*space + */ + irparams.AlreadyUsedTimingIntervalsOfCurrentInterval += 2; // We already consumed 2 to get here + if (irparams.AlreadyUsedTimingIntervalsOfCurrentInterval >= irparams.NumberOfTimingIntervalsInCurrentInterval){ + irparams.RawbuffOffsetForNextBiphaseLevel++; + } } #endif } else { -#if defined(LOCAL_DEBUG) - Serial.print(F("RC5: ")); - Serial.println(F("no transition found, decode failed")); -#endif + DEBUG_PRINT(F("RC5: no transition found, decode failed, BitIndex=")); + DEBUG_PRINTLN(tBitIndex); return false; } } // Success - decodedIRData.numberOfBits = tBitIndex; // must be RC5_BITS LongUnion tValue; tValue.ULong = tDecodedRawData; @@ -395,17 +407,27 @@ bool IRrecv::decodeRC5() { #if defined(DECODE_MARANTZ) if (RC5Marantz) { + decodedIRData.numberOfBits = tBitIndex - 1; // Above we count space handling as bit + decodedIRData.extra = tValue.UWord.LowWord & 0x3F; - decodedIRData.command = (tValue.UWord.LowWord > MARANTZ_COMMAND_EXTENSION_BITS) & 0x3F; + decodedIRData.command = (tValue.UWord.LowWord >> MARANTZ_COMMAND_EXTENSION_BITS) & 0x3F; decodedIRData.address = (tValue.ULong >> (RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS)) & 0x1F; - decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST; + // Get the inverted 7. command bit to decide if we have RC5X. For RC5, the inverted value is always 1 and serves as a second start bit. + if ((tValue.ULong & (1L << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS))) == 0) { + // Here we have detected RC5X! + decodedIRData.command += 0x40; + } + + decodedIRData.flags = IRDATA_FLAGS_IS_MSB_FIRST | IRDATA_FLAGS_EXTRA_INFO; if (tValue.ULong & (1L << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS))) { decodedIRData.flags |= IRDATA_FLAGS_TOGGLE_BIT; } decodedIRData.protocol = MARANTZ; } else { #endif + decodedIRData.numberOfBits = tBitIndex; // must be RC5_BITS + decodedIRData.command = tValue.UByte.LowByte & 0x3F; decodedIRData.address = (tValue.UWord.LowWord >> RC5_COMMAND_BITS) & 0x1F; @@ -429,6 +451,7 @@ bool IRrecv::decodeRC5() { return true; } +#endif // defined(DECODE_RC5) || defined(DECODE_MARANTZ) //+============================================================================= // RRRR CCCC 6666 @@ -439,19 +462,30 @@ bool IRrecv::decodeRC5() { //+============================================================================= // /* - Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first - +2650,- 850 - + 500,- 850 + 500,- 400 + 450,- 450 + 450,- 850 - +1400,- 400 + 450,- 450 + 450,- 450 + 450,- 900 - + 450,- 450 + 450,- 400 + 950,- 850 + 900,- 450 - + 450,- 450 + 450,- 850 + 950,- 400 + 450,- 900 - + 450 - Sum: 23150 + Protocol=RC6 Address=0xF1, Command=0x76, Raw-Data=0xF176, 20 bits, MSB first + +2700,- 850 + + 550,- 800 + 550,- 350 + 550,- 350 + 550,- 800 + +1400,- 400 + 550,- 400 + 550,- 350 + 550,- 800 + + 550,- 350 + 500,- 450 +1000,- 750 +1000,- 450 + + 500,- 400 + 500,- 850 + 950,- 450 + 550,- 750 + + 550 + Duration=23600us + + Protocol=RC6A Address=0xF1, Command=0x76, Extra=0x2711, Toggle=1, Raw-Data=0xA711F176, 35 bits, MSB first + +2700,- 850 + + 500,- 400 + 500,- 400 + 500,- 850 +1450,-1300 + +1000,- 850 + 550,- 350 +1000,- 400 + 550,- 350 + + 500,- 850 + 500,- 450 + 500,- 400 + 950,- 900 + + 500,- 400 + 550,- 350 +1000,- 400 + 500,- 400 + + 550,- 400 + 500,- 400 + 500,- 850 + 550,- 350 + + 550,- 400 +1000,- 800 +1000,- 400 + 500,- 400 + + 500,- 900 +1000,- 350 + 550,- 850 + 500 + Duration=37450us */ // Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit // Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits + 2666us pause - 37 bits incl. start bit -// !!! toggle bit has another timing :-( !!! -// mark->space => 1 +// !!! toggle bit has double timing !!! +// mark->space => 1 - Inverse of RC5! // space->mark => 0 // https://www.sbprojects.net/knowledge/ir/rc6.php // https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A @@ -560,25 +594,21 @@ void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe tIRRawData.UByte.LowByte = aCommand; tIRRawData.UByte.MidLowByte = aAddress; - tIRRawData.UWord.HighWord = 0; // must clear high word + tIRRawData.UWord.HighWord = 0; // must clear high word for the 3 mode bits to be 0 if (aEnableAutomaticToggle) { if (sLastSendToggleValue == 0) { sLastSendToggleValue = 1; - // set toggled bit - IR_DEBUG_PRINT(F("Set Toggle ")); + // set toggle bit tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0 } else { sLastSendToggleValue = 0; } } -#if defined(LOCAL_DEBUG) - Serial.print(F("RC6: ")); - Serial.print(F("sLastSendToggleValue=")); - Serial.print (sLastSendToggleValue); - Serial.print(F(" RawData=")); - Serial.println(tIRRawData.ULong, HEX); -#endif + DEBUG_PRINT(F("RC6: ToggleValue=")); + DEBUG_PRINT(sLastSendToggleValue); + DEBUG_PRINT(F(" RawData=")); + DEBUG_PRINTLN(tIRRawData.ULong, HEX); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { @@ -613,7 +643,6 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR if (sLastSendToggleValue == 0) { sLastSendToggleValue = 1; // set toggled bit - IR_DEBUG_PRINT(F("Set Toggle ")); tIRRawData.UByte.HighByte |= 0x80; // toggle bit is bit 32 } else { sLastSendToggleValue = 0; @@ -623,13 +652,10 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR // Set mode bits uint64_t tRawData = tIRRawData.ULong + 0x0600000000; -#if defined(LOCAL_DEBUG) - Serial.print(F("RC6A: ")); - Serial.print(F("sLastSendToggleValue=")); - Serial.print (sLastSendToggleValue); - Serial.print(F(" RawData=")); - Serial.println(tIRRawData.ULong, HEX); -#endif + DEBUG_PRINT(F("RC6A: ToggleValue=")); + DEBUG_PRINT(sLastSendToggleValue); + DEBUG_PRINT(F(" RawData=")); + DEBUG_PRINTLN(tIRRawData.ULong, HEX); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { @@ -646,8 +672,22 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR } } +#if defined(DECODE_RC6) /** * Try to decode data as RC6 protocol + * Unit is 444 us and half of RC5 unit 888 + * mark->space => 1 - Inverse of RC5! + * space->mark => 0 + * _ _ _ _ _ _ _ _ _ _ _ _ _ + * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | 444 us high and low + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value + * ______ _ _ _ _ + * Start bit for RC6 _____| |_| |___| |_| |_| ......|.......|.. + * Start 1 0 0 0 ^double timing toggle bit + 8 bit address + 8 bit command + * ______ _ _ _ _ _ + * Start bit for RC6A _____| |_| |_| |_| |___| ......|...... |_.. + * Start 1 1 1 0 toggle^ bit 1 + 14 bit extra + 8 bit address + 8 bit command */ bool IRrecv::decodeRC6() { uint8_t tBitIndex; @@ -655,18 +695,16 @@ bool IRrecv::decodeRC6() { // Check we have the right amount of data (). The +3 for initial gap, start bit mark and space if (decodedIRData.rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawlen) { - IR_DEBUG_PRINT(F("RC6: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not between 15 and 25")); + DEBUG_PRINT(F("RC6: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not between 15 and 25")); return false; } // Check header "mark" and "space", this must be done for repeat and data if (!matchMark(irparams.rawbuf[1], RC6_HEADER_MARK) || !matchSpace(irparams.rawbuf[2], RC6_HEADER_SPACE)) { // no debug output, since this check is mainly to determine the received protocol - IR_DEBUG_PRINT(F("RC6: ")); - IR_DEBUG_PRINTLN(F("Header mark or space length is wrong")); + DEBUG_PRINTLN(F("RC6: Header mark or space length is wrong")); return false; } @@ -675,18 +713,16 @@ bool IRrecv::decodeRC6() { // Check first bit, which is known to be a 1 (mark->space) if (getBiphaselevel() != MARK) { - IR_DEBUG_PRINT(F("RC6: ")); - IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK")); + DEBUG_PRINTLN(F("RC6: first getBiphaselevel() is not MARK")); return false; } // Check second bit if (getBiphaselevel() != SPACE) { - IR_DEBUG_PRINT(F("RC6: ")); - IR_DEBUG_PRINTLN(F("second getBiphaselevel() is not SPACE")); + DEBUG_PRINTLN(F("RC6: second getBiphaselevel() is not SPACE")); return false; } - for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) { + for (tBitIndex = 0; irparams.RawbuffOffsetForNextBiphaseLevel < decodedIRData.rawlen; tBitIndex++) { uint8_t tStartLevel; // start level of coded bit uint8_t tEndLevel; // end level of coded bit @@ -698,18 +734,12 @@ bool IRrecv::decodeRC6() { * Toggle bit is double wide; level of 1. and 2. time slot and 3. and 4.time slot must be equal */ if (tStartLevel != tEndLevel) { // 1. and 2. time slot must be equal -#if defined(LOCAL_DEBUG) - Serial.print(F("RC6: ")); - Serial.println(F("Toggle mark or space length is wrong")); -#endif + DEBUG_PRINTLN(F("RC6: Toggle mark or space length is wrong")); return false; } tEndLevel = getBiphaselevel(); if (tEndLevel != getBiphaselevel()) { // 3. and 4. time slot must be equal -#if defined(LOCAL_DEBUG) - Serial.print(F("RC6: ")); - Serial.println(F("Toggle mark or space length is wrong")); -#endif + DEBUG_PRINTLN(F("RC6: Toggle mark or space length is wrong")); return false; } } @@ -724,10 +754,7 @@ bool IRrecv::decodeRC6() { // we have a space to mark transition here tDecodedRawData = (tDecodedRawData << 1) | 0; } else { -#if defined(LOCAL_DEBUG) - Serial.print(F("RC6: ")); - Serial.println(F("Decode failed")); -#endif + DEBUG_PRINTLN(F("RC6: Decode failed")); // we have no transition here or one level is -1 -> error return false; // Error } @@ -771,6 +798,7 @@ bool IRrecv::decodeRC6() { return true; } +#endif // #if defined(DECODE_RC6) /********************************************************************************* * Old deprecated functions, kept for backward compatibility to old 2.0 tutorials @@ -867,7 +895,6 @@ void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_RC5_RC6_HPP diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index adf77450f..6b23bc724 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -32,11 +32,7 @@ #ifndef _IR_SAMSUNG_HPP #define _IR_SAMSUNG_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -276,10 +272,9 @@ bool IRrecv::decodeSamsung() { // Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark if (decodedIRData.rawlen != ((2 * SAMSUNG_BITS) + 4) && decodedIRData.rawlen != ((2 * SAMSUNG48_BITS) + 4) && (decodedIRData.rawlen != 6)) { - IR_DEBUG_PRINT(F("Samsung: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 6 or 68 or 100")); + DEBUG_PRINT(F("Samsung: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 6 or 68 or 100")); return false; } @@ -418,7 +413,6 @@ void IRsend::sendSAMSUNG(unsigned long data, int nbits) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_SAMSUNG_HPP diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index d97ff575d..72c136852 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -8,6 +8,8 @@ ************************************************************************************ * MIT License * + * Copyright (c) 2020-2026 Armin Joachimsmeyer + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -30,11 +32,7 @@ #ifndef _IR_SONY_HPP #define _IR_SONY_HPP -#if defined(DEBUG) -#define LOCAL_DEBUG -#else -//#define LOCAL_DEBUG // This enables debug output only for this file -#endif +#include "LocalDebugLevelStart.h" /** \addtogroup Decoder Decoders and encoders for different protocols * @{ @@ -65,7 +63,7 @@ // see https://www.sbprojects.net/knowledge/ir/sirc.php // https://www.mikrocontroller.net/articles/IRMP_-_english#SIRCS // Frames are repeated every 45ms (measured from start to start) for as long as the key on the remote control is held down. -// This leads to a 15 ms gap for a Sony20 protocol! +// This leads to a 12 ms gap for a Sony20 protocol! // Here http://picprojects.org.uk/projects/sirc/ it is claimed, that many Sony remotes send each frame a minimum of 3 times. But 1 repeat (2 sends) has also been seen in real life. // LSB first, start bit + 7 command + 5 to 13 address, no stop bit // IRP: Sony12 {40k,600}<1,-1|2,-1>(4,-1,F:7,D:5,^45m)+ ==> 40 kHz, Unit is 600, LSB, One mark is 2 units, Start bit is 4 units, 7 bit Function, 5 bit Device, no Stop bit, every 45 milliseconds @@ -115,10 +113,9 @@ bool IRrecv::decodeSony() { // Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42 if (decodedIRData.rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_MAX) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_15) + 2) { - IR_DEBUG_PRINT(F("Sony: ")); - IR_DEBUG_PRINT(F("Data length=")); - IR_DEBUG_PRINT(decodedIRData.rawlen); - IR_DEBUG_PRINTLN(F(" is not 12, 15 or 20")); + DEBUG_PRINT(F("Sony: Data length=")); + DEBUG_PRINT(decodedIRData.rawlen); + DEBUG_PRINTLN(F(" is not 12, 15 or 20")); return false; } @@ -157,9 +154,8 @@ bool IRrecv::decodeSonyMSB(decode_results *aResults) { // Some Sony's deliver repeats fast after first // unfortunately can't spot difference from of repeat from two fast clicks if (aResults->rawbuf[0] < (SONY_DOUBLE_SPACE_USECS / MICROS_PER_TICK)) { -#if defined(LOCAL_DEBUG) - Serial.println(F("IR Gap found")); -#endif + DEBUG_PRINTLN(F("IR Gap found")); + aResults->bits = 0; aResults->value = 0xFFFFFFFF; decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT; @@ -223,7 +219,6 @@ void IRsend::sendSony(unsigned long data, int nbits) { } /** @}*/ -#if defined(LOCAL_DEBUG) -#undef LOCAL_DEBUG -#endif +#include "LocalDebugLevelEnd.h" + #endif // _IR_SONY_HPP diff --git a/src/ir_Template.hpp b/src/ir_Template.hpp index f4726da42..6ca74d918 100644 --- a/src/ir_Template.hpp +++ b/src/ir_Template.hpp @@ -92,6 +92,8 @@ #ifndef _IR_SHUZU_HPP #define _IR_SHUZU_HPP +#include "LocalDebugLevelStart.h" + //============================================================================== // // @@ -155,8 +157,7 @@ bool IRrecv::decodeShuzu() { // Decode if (!decodePulseDistanceData_P(&ShuzuProtocolConstants, SHUZU_BITS)) { - IR_DEBUG_PRINT(F("Shuzu: ")); - IR_DEBUG_PRINTLN(F("Decode failed")); + DEBUG_PRINTLN(F("Shuzu: Decode failed")); return false; } @@ -172,4 +173,7 @@ bool IRrecv::decodeShuzu() { return true; } + +#include "LocalDebugLevelEnd.h" + #endif // _IR_SHUZU_HPP From 562edd8ae07997670c029bdb862e9723963130a2 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 22 Feb 2026 00:50:51 +0100 Subject: [PATCH 118/133] Documented 8 bit buffer usage --- README.md | 5 +- examples/AllProtocolsOnLCD/ADCUtils.h | 2 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 5 + .../ReceiveAndSendDistanceWidth.ino | 2 +- examples/ReceiveDemo/ReceiveDemo.ino | 9 +- examples/ReceiveDump/ReceiveDump.ino | 3 +- examples/SendAndReceive/SendAndReceive.ino | 1 + examples/SendDemo/SendDemo.ino | 10 +- examples/UnitTest/UnitTest.ino | 15 +- src/IRCommandDispatcher.h | 4 +- src/IRCommandDispatcher.hpp | 22 ++- src/IRReceive.hpp | 45 +++--- src/IRSend.hpp | 60 ++++---- src/IRremote.hpp | 23 ++-- src/IRremoteInt.h | 84 ++++++------ src/ir_BangOlufsen.hpp | 129 +++++++++--------- src/ir_DistanceWidthProtocol.hpp | 10 +- src/ir_Kaseikyo.hpp | 2 +- src/ir_RC5_RC6.hpp | 6 +- 19 files changed, 226 insertions(+), 211 deletions(-) diff --git a/README.md b/README.md index 6acc62bef..1de92f91b 100644 --- a/README.md +++ b/README.md @@ -423,10 +423,10 @@ 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. + IRDecodedRawDataType decodedRawData; // Up to 32 (64 bit for 32 bit CPU architectures) bit decoded raw data, used for sendRaw functions. #if defined(DECODE_DISTANCE_WIDTH) DistanceWidthTimingInfoStruct DistanceWidthTimingInfo; // 12 bytes - IRRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; // 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions. + IRDecodedRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; // 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions. #endif uint16_t numberOfBits; // Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. uint8_t flags; // IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions @@ -1016,6 +1016,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | Name | Default value | Description | |-|-:|-| | `RAW_BUFFER_LENGTH` | 200 | Buffer size of raw input uint16_t buffer. Must be even! If it is too small, overflow flag will be set. 100 is sufficient for *regular* protocols of up to 48 bits, but for most air conditioner protocols a value of up to 750 is required. Use the ReceiveDump example to find smallest value for your requirements. A value of 200 requires 200 bytes RAM. | +| `USE_16_BIT_TIMING_BUFFER` | disabled | Use a 16-bit buffer if raw timing capture is required and exact values above 12750 us must be preserved. This doubles the RAM size of the buffer. | | `EXCLUDE_UNIVERSAL_PROTOCOLS` | disabled | Excludes the universal decoder for pulse distance width protocols and decodeHash (special decoder for all protocols) from `decode()`. Saves up to 1000 bytes program memory. | | `EXCLUDE_EXOTIC_PROTOCOLS` | disabled | Excludes BANG_OLUFSEN, BOSEWAVE, WHYNTER, FAST LEGO_PF, and OpenLASIR from `decode()` and from sending with `IrSender.write()`. Saves up to 650 bytes program memory. | | `DECODE_` | all | Selection of individual protocol(s) to be decoded. You can specify multiple protocols. See [here](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/IRremote.hpp#L98-L121) | diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index eb4928e72..013349b2d 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -228,7 +228,7 @@ bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimp #endif // defined(__AVR__) ... /* - * Variables and functions defined as dummies to allow for seamless compiling on non AVR platforms + * The next variables and functions are defined as stubs on non-AVR platforms to allow for seamless compiling */ extern float sVCCVoltage; extern uint16_t sVCCVoltageMillivolt; diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index bdc61d1ea..0c796c852 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -74,8 +74,13 @@ #if !defined(RAW_BUFFER_LENGTH) // For air condition remotes it may require up to 750. Default is 200. # if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 700 // we require 2 buffer of this size for this example # endif +# if !((defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)) +// Here we most likely have 4 k RAM or more +#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us +# endif #endif //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index cece3cc79..263b42eb2 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -82,7 +82,7 @@ #define DELAY_BETWEEN_REPEATS_MILLIS 70 // Storage for the recorded code, pre-filled with NEC data -IRRawDataType sDecodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34 +IRDecodedRawDataType sDecodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE] = { 0x7B34ED12 }; // Initialize with NEC address 0x12 and command 0x34 DistanceWidthTimingInfoStruct sDistanceWidthTimingInfo = { 9000, 4500, 560, 1690, 560, 560 }; // Initialize with NEC timing uint8_t sNumberOfBits = 32; diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 4929717b7..e13a782a3 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -10,7 +10,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -92,11 +92,12 @@ # endif #endif -//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory +//#define NO_LED_FEEDBACK_CODE // saves 92 bytes program memory //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. -//#define EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active -//#define 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 EXCLUDE_EXOTIC_PROTOCOLS // saves around 650 bytes program memory if all other protocols are active +//#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 1 bytes program memory. //#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory +//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us // 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. diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index c0af4cb37..8415b4ad8 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -10,7 +10,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2020-2025 Armin Joachimsmeyer + * Copyright (c) 2020-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -53,6 +53,7 @@ * between sender and receiver as well as with the ambient light intensity. */ //#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity. +//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us //#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define DEBUG // Activate this for lots of lovely debug output from the decoders. diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index eec023f16..549541ab7 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -44,6 +44,7 @@ //#define NO_LED_FEEDBACK_CODE // saves 318 bytes program memory //#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 44 bytes program memory //#define NO_LED_SEND_FEEDBACK_CODE // Saves 36 bytes program memory +//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us //#define DEBUG // Activate this for lots of lovely debug output from the decoders. diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index b916d9679..32a22f689 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -55,11 +55,11 @@ #define DELAY_AFTER_LOOP 5000 #if __INT_WIDTH__ < 32 -IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first +IRDecodedRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first /* * Alternative definition of tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010} * But be aware, that this requires a cast when using tRawDataPGM as parameter. - * Like sendPulseDistanceWidthFromPGMArray_P(..., (IRRawDataType*) &tRawDataPGM[0], ...); + * Like sendPulseDistanceWidthFromPGMArray_P(..., (IRDecodedRawDataType*) &tRawDataPGM[0], ...); */ //uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/ //0x10, 0xA0, 0x0, 0x0, /*0xA010*/}; @@ -234,7 +234,7 @@ void loop() { 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 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant # else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant # endif @@ -248,7 +248,7 @@ void loop() { Serial.println(F(" LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48, + IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRDecodedRawDataType*) tRawDataPGM, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); # else IrSender.sendPulseDistanceWidth(38, 3450, 1700, 450, 1250, 450, 400, 0xA010B02002, 48, PROTOCOL_IS_LSB_FIRST, 0, @@ -258,7 +258,7 @@ void loop() { // The same with MSB first. Use bit reversed raw data of LSB first part Serial.println(F(" MSB first")); - IRRawDataType tRawData[4]; + IRDecodedRawDataType tRawData[4]; # if __INT_WIDTH__ < 32 tRawData[0] = 0x40040D00; // MSB of tRawData[0] is sent first tRawData[1] = 0x805; diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index a2b587dee..e2f428c83 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -56,6 +56,7 @@ #define NO_LED_FEEDBACK_CODE // Saves 270 bytes program memory //#define NO_LED_RECEIVE_FEEDBACK_CODE // Saves 176 bytes program memory //#define NO_LED_SEND_FEEDBACK_CODE // Saves 38 bytes program memory +//#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER @@ -138,7 +139,7 @@ volatile bool sDataJustReceived = false; void ReceiveCompleteCallbackHandler(); #if __INT_WIDTH__ < 32 -//IRRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first +//IRDecodedRawDataType const tRawDataPGM[] PROGMEM = { 0xB02002, 0xA010 }; // LSB of tRawData[0] is sent first uint8_t const tRawDataPGM[] PROGMEM = { 0x02, 0x20, 0xB0, 0x00, /*0xB02002*/ 0x10, 0xA0, 0x0, 0x0, /*0xA010*/}; // Define tRawDataPGM as byte array of same size with same content as { 0xB02002, 0xA010} #endif @@ -254,7 +255,7 @@ void setup() { } -void checkReceivedRawData(IRRawDataType aRawData) { +void checkReceivedRawData(IRDecodedRawDataType aRawData) { // wait until signal has received while (!sDataJustReceived) { }; @@ -306,7 +307,7 @@ void checkReceivedRawData(IRRawDataType aRawData) { } #if defined(DECODE_DISTANCE_WIDTH) -void checkReceivedArray(IRRawDataType *aRawDataArrayPointer, uint8_t aArraySize) { +void checkReceivedArray(IRDecodedRawDataType *aRawDataArrayPointer, uint8_t aArraySize) { // wait until signal has received while (!sDataJustReceived) { }; @@ -535,7 +536,7 @@ void loop() { /* * Do this only once at the first loop */ - IRRawDataType tRawData[4]; + IRDecodedRawDataType tRawData[4]; /* * Test send usage for UNKNOWN protocol @@ -604,7 +605,7 @@ void loop() { 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 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceive(0x0B, 0x10); # else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant @@ -619,7 +620,7 @@ void loop() { Serial.println(F("-LSB first")); Serial.flush(); # if __INT_WIDTH__ < 32 - IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRRawDataType*) tRawDataPGM, 48, + IrSender.sendPulseDistanceWidthFromPGMArray(38, 3450, 1700, 450, 1250, 450, 400, (IRDecodedRawDataType*) tRawDataPGM, 48, PROTOCOL_IS_LSB_FIRST, 0, NO_REPEATS); checkReceive(0x0B, 0x10); # else @@ -774,7 +775,7 @@ void loop() { 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 - IRRawDataType tRawData1[2]; + IRDecodedRawDataType tRawData1[2]; tRawData1[0] = 0x01AF37FC; // We have 1 header (start) bit and 7 start bits and 31 address bits for MagiQuest, so 0x6BCDFF00 is shifted 2 left tRawData1[1] = 0x017619; // We send only 23 bits here! 0x19 is the checksum IrSender.sendPulseDistanceWidthFromArray(38, 287, 864, 576, 576, 287, 864, &tRawData1[0], 55, diff --git a/src/IRCommandDispatcher.h b/src/IRCommandDispatcher.h index 74b362c63..ad77b7895 100644 --- a/src/IRCommandDispatcher.h +++ b/src/IRCommandDispatcher.h @@ -103,8 +103,8 @@ class IRCommandDispatcher { // The main dispatcher function void checkAndCallCommand(bool aCallBlockingCommandImmediately); - void printIRCommandString(Print *aSerial); - void printIRCommandString(Print *aSerial, uint_fast8_t aMappingArrayIndex); + void printIRCommandString(Print *aSerial, IRCommandType aCommand); + void printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex); void setRequestToStopReceived(bool aRequestToStopReceived = true); IRCommandType currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command diff --git a/src/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp index bbbbd3d73..c82d99c8f 100644 --- a/src/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -436,7 +436,7 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { IRReceivedData.command = BlockingCommandToRunNext; BlockingCommandToRunNext = COMMAND_EMPTY; IRReceivedData.isRepeat = false; - requestToStopReceived = false; // Do not stop the command executed now + requestToStopReceived = false; // Signal to main loop to stop the command currently executed checkAndCallCommand(true); return true; } @@ -447,8 +447,16 @@ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { * Not used internally */ void IRCommandDispatcher::setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext) { - INFO_PRINT(F("Set next command to run to 0x")); - INFO_PRINTLN(aBlockingCommandToRunNext, HEX); +#if defined(LOCAL_INFO) + Serial.print(F("Set next command to run to 0x")); + Serial.print(aBlockingCommandToRunNext, HEX); +# if defined(USE_DISPATCHER_COMMAND_STRINGS) + Serial.print('|'); + printIRCommandString(&Serial, aBlockingCommandToRunNext); +# endif + Serial.println(); +#endif + BlockingCommandToRunNext = aBlockingCommandToRunNext; requestToStopReceived = true; } @@ -468,7 +476,7 @@ bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) { return false; } -void IRCommandDispatcher::printIRCommandString(Print *aSerial, uint_fast8_t aMappingArrayIndex) { +void IRCommandDispatcher::printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex) { #if defined(__AVR__) # if defined(USE_DISPATCHER_COMMAND_STRINGS) aSerial->println(reinterpret_cast(IRMapping[aMappingArrayIndex].CommandString)); @@ -486,10 +494,10 @@ void IRCommandDispatcher::printIRCommandString(Print *aSerial, uint_fast8_t aMap #endif } -void IRCommandDispatcher::printIRCommandString(Print *aSerial) { +void IRCommandDispatcher::printIRCommandString(Print *aSerial, IRCommandType aCommand) { for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { - if (IRReceivedData.command == IRMapping[i].IRCode) { - printIRCommandString(aSerial, i); + if (aCommand == IRMapping[i].IRCode) { + printIRCommandStringForArrayIndex(aSerial, i); return; } } diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index ee8562d09..7e5265e27 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -46,6 +46,8 @@ #define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative #endif +unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer() + /** \addtogroup Receiving Receiving IR data for multiple protocols * @{ */ @@ -54,12 +56,6 @@ */ IRrecv IrReceiver; -/* - * The control structure 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. @@ -177,7 +173,8 @@ void IRrecv::ReceiveInterruptHandler() { #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 !defined(USE_16_BIT_TIMING_BUFFER) + // Clip timings > 12750 us (255 * 50) to 12750 if (tTickCounterForISR > UINT8_MAX) { tTickCounterForISR = UINT8_MAX; } @@ -234,7 +231,8 @@ void IRrecv::ReceiveInterruptHandler() { #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 !defined(USE_16_BIT_TIMING_BUFFER) + // Clip timings > 12750 us (255 * 50) to 12750 if (tTickCounterForISR > UINT8_MAX) { tTickCounterForISR = UINT8_MAX; } @@ -765,8 +763,8 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy DEBUG_PRINT(aIsPulseWidthProtocol); DEBUG_PRINTLN(); - IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop - IRRawDataType tMask = 1UL; // Mask is only used for LSB first + IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop + IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; for (uint_fast8_t i = aNumberOfBits; i > 0; i--) { @@ -841,8 +839,8 @@ void IRrecv::decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBit DEBUG_PRINT(aIsPulseWidthProtocol); DEBUG_PRINTLN(); - IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop - IRRawDataType tMask = 1UL; // Mask is only used for LSB first + IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop + IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first auto *tRawBufPointer = &irparams.rawbuf[aStartOffset]; for (uint_fast8_t i = aNumberOfBits; i > 0; i--) { @@ -891,8 +889,8 @@ void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenTy 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 + IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop + IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first for (uint_fast8_t i = aNumberOfBits; i > 0; i--) { // get one mark and space pair @@ -967,8 +965,8 @@ bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRa bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> 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 + IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop + IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first for (uint_fast8_t i = aNumberOfBits; i > 0; i--) { // get one mark and space pair @@ -1886,7 +1884,7 @@ uint32_t IRrecv::getTotalDurationOfRawData() { for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { tSumOfDurationTicks += irparams.rawbuf[i]; } - return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK; + return (uint32_t) tSumOfDurationTicks * MICROS_PER_TICK; } // @formatter:off @@ -2242,7 +2240,7 @@ void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInste // Dump data for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) { - uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; + uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; // no problem to use 50 instead of 50L here! if (aDoCompensate) { if (i & 1) { @@ -2263,10 +2261,8 @@ void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInste tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; aSerial->print(tTicks); } - if (i + 1 < decodedIRData.rawlen) - aSerial->print(','); // ',' not required on last one - if (!(i & 1)) - aSerial->print(' '); + if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one + if (!(i & 1)) aSerial->print(' '); } // End declaration @@ -2282,8 +2278,7 @@ void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInste * * 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). + * Maximum for uint8_t is 255*50 microseconds = 12750 microseconds = 12.75 ms, which hardly ever occurs inside an IR frame. * @param aArrayPtr Address of an array provided by the caller. */ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) { @@ -2291,7 +2286,7 @@ void IRrecv::compensateAndStoreIRResultInArray(uint8_t *aArrayPtr) { // Store data, skip leading space# IRRawlenType i; for (i = 1; i < decodedIRData.rawlen; i++) { - uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; + uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; // no problem to use 50 instead of 50L here! if (i & 1) { // Mark tDuration -= MARK_EXCESS_MICROS; diff --git a/src/IRSend.hpp b/src/IRSend.hpp index d338ad8cd..d702c2390 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -561,7 +561,7 @@ void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengt enableIROut(aIRFrequencyKilohertz); for (uint_fast16_t i = 0; i < aLengthOfBuffer; i++) { - uint16_t duration = pgm_read_byte(&aPGMBufferWithTicks[i]) * (uint_fast16_t) MICROS_PER_TICK; + uint16_t duration = pgm_read_byte(&aPGMBufferWithTicks[i]) * MICROS_PER_TICK; if (i & 1) { // Odd space(duration); @@ -609,7 +609,7 @@ void IRsend::sendRaw_P(const uint8_t aPGMBufferWithTicks[], uint_fast16_t aLengt * @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) { + uint16_t aZeroSpaceMicros, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags) { DEBUG_PRINT(aData, HEX); DEBUG_PRINT('|'); @@ -617,7 +617,7 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp DEBUG_FLUSH(); // For MSBFirst, send data from MSB to LSB until mask bit is shifted out - IRRawDataType tMask = 1ULL << (aNumberOfBits - 1); + IRDecodedRawDataType 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))) { TRACE_PRINT('1'); @@ -659,7 +659,7 @@ void IRsend::sendPulseDistanceWidthData(uint16_t aOneMarkMicros, uint16_t aOneSp * @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, +void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits) { sendPulseDistanceWidthData(aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros, @@ -667,7 +667,7 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags); } -void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, +void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; @@ -691,7 +691,7 @@ void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants co * @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, + uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)()) { @@ -738,14 +738,14 @@ void IRsend::sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeader 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, + IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { // Set IR carrier frequency enableIROut(aFrequencyKHz); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; - uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1; + uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE) + 1; #if defined(LOCAL_DEBUG) // fist data @@ -778,13 +778,13 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_ tFlags = aFlags; } else { // intermediate data - tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; + tNumberOfBitsForOneSend = BITS_IN_DECODED_RAW_DATA_TYPE; tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend, tFlags); - aNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + aNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE; } tNumberOfCommands--; @@ -803,14 +803,14 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, uint16_ 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, + IRDecodedRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { // Set IR carrier frequency enableIROut(aFrequencyKHz); uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; - uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1; + uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE) + 1; #if defined(LOCAL_DEBUG) // fist data @@ -843,11 +843,11 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint tFlags = aFlags; } else { // intermediate data - tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; + tNumberOfBitsForOneSend = BITS_IN_DECODED_RAW_DATA_TYPE; tFlags = aFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } - IRRawDataType tDecodedRawData; + IRDecodedRawDataType tDecodedRawData; #if (__INT_WIDTH__ < 32) tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]); // pgm_read_dword reads 32 bit on AVR #else @@ -855,7 +855,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint #endif sendPulseDistanceWidthData(aOneMarkMicros, aOneSpaceMicros, aZeroMarkMicros, aZeroSpaceMicros, tDecodedRawData, tNumberOfBitsForOneSend, tFlags); - aNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + aNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE; } tNumberOfCommands--; @@ -884,7 +884,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(uint_fast8_t aFrequencyKHz, uint * @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, + IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidthFromArray(aFrequencyKHz, aDistanceWidthTimingInfo->HeaderMarkMicros, aDistanceWidthTimingInfo->HeaderSpaceMicros, aDistanceWidthTimingInfo->OneMarkMicros, @@ -894,7 +894,7 @@ void IRsend::sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, Distanc } void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz, - DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRRawDataType *aDecodedRawDataArray, + DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats) { DistanceWidthTimingInfoStruct tTemporaryDistanceWidthTimingInfo; @@ -914,7 +914,7 @@ void IRsend::sendPulseDistanceWidthFromArray_P(uint_fast8_t aFrequencyKHz, * @param aNumberOfRepeats If < 0 and a aProtocolConstants->SpecialSendRepeatFunction() is specified * then it is called without leading and trailing space. */ -void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, +void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { DEBUG_PRINT(F("Data=0x")); @@ -980,7 +980,7 @@ void IRsend::sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtoc * then it is called without leading and trailing space. */ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, - IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { + IRDecodedRawDataType *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, @@ -992,7 +992,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants // Set IR carrier frequency enableIROut(aProtocolConstants->FrequencyKHz); - uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1; + uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE) + 1; #if defined(LOCAL_DEBUG) // fist data @@ -1027,7 +1027,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants tFlags = tOriginalFlags; } else { // intermediate data - tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; + tNumberOfBitsForOneSend = BITS_IN_DECODED_RAW_DATA_TYPE; tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } @@ -1036,7 +1036,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aDecodedRawDataArray[i], tNumberOfBitsForOneSend, tFlags); - tNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + tNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE; } tNumberOfCommands--; @@ -1054,7 +1054,7 @@ void IRsend::sendPulseDistanceWidthFromArray(PulseDistanceWidthProtocolConstants } void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, - IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { + IRDecodedRawDataType const *aDecodedRawDataPGMArray, 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, @@ -1066,7 +1066,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta // Set IR carrier frequency enableIROut(aProtocolConstants->FrequencyKHz); - uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE) + 1; + uint_fast8_t tNumberOf32Or64BitChunks = ((aNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE) + 1; #if defined(LOCAL_DEBUG) // fist data @@ -1101,11 +1101,11 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta tFlags = tOriginalFlags; } else { // intermediate data - tNumberOfBitsForOneSend = BITS_IN_RAW_DATA_TYPE; + tNumberOfBitsForOneSend = BITS_IN_DECODED_RAW_DATA_TYPE; tFlags = tOriginalFlags | SUPPRESS_STOP_BIT; // No stop bit for leading data } - IRRawDataType tDecodedRawData; + IRDecodedRawDataType tDecodedRawData; #if (__INT_WIDTH__ < 32) tDecodedRawData = pgm_read_dword(&aDecodedRawDataPGMArray[i]); // pgm_read_dword reads 32 bit on AVR #else @@ -1115,7 +1115,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, tDecodedRawData, tNumberOfBitsForOneSend, tFlags); - tNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + tNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE; } tNumberOfCommands--; @@ -1137,7 +1137,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConsta **********************************************************************************************************************/ void IRsend::sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, - IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { + IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, @@ -1146,7 +1146,7 @@ void IRsend::sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstan aNumberOfRepeats); } void IRsend::sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, - IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { + IRDecodedRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, @@ -1155,7 +1155,7 @@ void IRsend::sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolCons aNumberOfRepeats); } -void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, +void IRsend::sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 75efff709..210ed20fc 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -113,17 +113,25 @@ #endif /** - * Minimum gap between IR transmissions, to detect the end of a protocol. + * Minimum gap between IR transmissions, only used to detect the end of a frame. * Must be greater than any space of a protocol e.g. the NEC header space of 4500 us. - * Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 12 ms for Sony20 protocol. - * Keep in mind, that this is the delay between the end of the received command and the start of decoding. + * Must be smaller than any gap between a frame and a repeat frame; e.g. the retransmission gap for Sony is around 12 ms for Sony20 protocol. + * Bear in mind, that this is the delay between the end of the received frame + * and the time at which the software detects the end of this frame and can start decoding! */ #if !defined(RECORD_GAP_MICROS) // To change this value, you simply can add a line #define "RECORD_GAP_MICROS " in your *.ino file before the line "#include " // Maximum value for RECORD_GAP_MICROS, which fit into 8 bit buffer, using 50 us as tick, is 12750 #define RECORD_GAP_MICROS 8000 // RECS80 (https://www.mikrocontroller.net/articles/IRMP#RECS80) 1 bit space is 7500µs , NEC header space is 4500 #endif -#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 160 +#define RECORD_GAP_TICKS (RECORD_GAP_MICROS / MICROS_PER_TICK) // 160 for RECORD_GAP_MICROS == 8000 + +/** + * microseconds per clock interrupt tick + */ +#if !defined(MICROS_PER_TICK) +#define MICROS_PER_TICK 50 // We do not need it to be 50L!!! It saves 90 bytes for UnitTest compared with 50L :-) +#endif /** * Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a higher value. @@ -204,13 +212,6 @@ #define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code #endif -/** - * microseconds per clock interrupt tick - */ -#if ! defined(MICROS_PER_TICK) -#define MICROS_PER_TICK 50L // must be with L to get 32 bit results if multiplied with rawbuf[] content. -#endif - #define MILLIS_IN_ONE_SECOND 1000L #define MICROS_IN_ONE_SECOND 1000000L #define MICROS_IN_ONE_MILLI 1000L diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 605de5734..8cbba57dd 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -89,25 +89,24 @@ typedef unsigned int IRRawlenType; #endif /* - * Use 8 bit buffer for IR timing in 50 ticks units. - * It is save to use 8 bit if RECORD_GAP_TICKS < 256, since any value greater 255 is interpreted as frame gap of 12750 us. - * The default for frame gap is currently 8000! - * But if we assume that for most protocols the frame gap is way greater than the biggest mark or space duration, - * 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. + * We store IR timing values in an 8-bit buffer, where each unit represents 50 ticks. + * Since 8 bits can hold values from 0 to 255, the maximum measurable timing is 255 × 50 ticks = 12750 us. + * + * This means: + * - Any timing up to 12750 us is stored accurately. + * - Any timing greater than 12750 us is clipped and stored as 12750 us. + * - Therefore, you can detect that a timing exceeded 12750 us (because it appears as 12750 us). + * - However, you cannot distinguish between two different timings if both are greater than 12750 us — they will both appear as the same maximum value. + * + * For decoding purposes, 8 bits are acceptable as long as the protocol does not require distinguishing between two different timings + * that are both longer than 12750 us. + * As I am not currently (02/2026) aware of any protocols that require this, we use 8 bits. + * Use a 16-bit buffer if raw timing capture is required and exact values above 12750 us must be preserved. */ -#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. +#if !defined(USE_16_BIT_TIMING_BUFFER) // Use uint16_t buffer for timing. Doubles the RAM requirement. this can be used to override our selection of 8 the bit array +typedef uint8_t IRRawbufType; // all timings up to 12750 us fit into 8 bit (for MICROS_PER_TICK == 50). #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. -#endif - -#if (__INT_WIDTH__ < 32) -typedef uint32_t IRRawDataType; -#define BITS_IN_RAW_DATA_TYPE 32 -#else -typedef uint64_t IRRawDataType; -#define BITS_IN_RAW_DATA_TYPE 64 +typedef uint16_t IRRawbufType; // Use 16 bit array #endif /********************************************************** @@ -148,9 +147,14 @@ 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. }; -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. +#if (__INT_WIDTH__ < 32) +typedef uint32_t IRDecodedRawDataType; +#define BITS_IN_DECODED_RAW_DATA_TYPE 32 +#else +typedef uint64_t IRDecodedRawDataType; +#define BITS_IN_DECODED_RAW_DATA_TYPE 64 +#endif +#define DECODED_RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_DECODED_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. @@ -160,11 +164,11 @@ struct IRData { 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. + IRDecodedRawDataType 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. + IRDecodedRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; ///< 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions. #endif uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible. uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above @@ -200,6 +204,8 @@ struct decode_results { bool overflow; // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long }; +extern unsigned long sMicrosAtLastStopTimer; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer() + /** * Main class for receiving IR signals */ @@ -399,7 +405,7 @@ class IRrecv { uint16_t lastDecodedAddress; uint16_t lastDecodedCommand; #if defined(DECODE_DISTANCE_WIDTH) - IRRawDataType lastDecodedRawData; + IRDecodedRawDataType lastDecodedRawData; #endif uint8_t repeatCount; // Used e.g. for Denon decode for autorepeat decoding. @@ -532,47 +538,47 @@ class IRsend { */ 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, + IRDecodedRawDataType *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); + IRDecodedRawDataType 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); + IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); void sendPulseDistanceWidthFromPGMArray(PulseDistanceWidthProtocolConstants *aProtocolConstants, - IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); + IRDecodedRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); void sendPulseDistanceWidthFromArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, - IRRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); + IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); void sendPulseDistanceWidthFromPGMArray_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, - IRRawDataType const *aDecodedRawDataPGMArray, uint16_t aNumberOfBits, int_fast8_t aNumberOfRepeats); + IRDecodedRawDataType 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, + IRDecodedRawDataType *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, + DistanceWidthTimingInfoStruct const *aDistanceWidthTimingInfoPGM, IRDecodedRawDataType *aDecodedRawDataArray, uint16_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats); - void sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, + void sendPulseDistanceWidth(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats); - void sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, + void sendPulseDistanceWidth_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, int_fast8_t aNumberOfRepeats); - void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRRawDataType aData, + void sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits); - void sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRRawDataType aData, + void sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType 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, + IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, 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, + IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis, 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); + uint16_t aZeroSpaceMicros, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags); void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits, bool aSendStartBit = true); void mark(uint16_t aMarkMicros); diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 16ccb502d..2716757f4 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -52,11 +52,9 @@ //============================================================================== // https://www.mikrocontroller.net/attachment/33137/datalink.pdf // https://www.mikrocontroller.net/articles/IRMP_-_english#B&O - +// BEO is a Pulse Distance Protocol with 200 us pulse // This protocol is unusual in two ways: - // 1. The carrier frequency is 455 kHz - // You can build your own receiver as Bang & Olufsen did (check old schematics) or use a TSOP7000 // Vishay stopped producing TSOP7000 since 2009 so you will probably only find counterfeits: // https://www.vishay.com/files/whatsnew/doc/ff_FastFacts_CounterfeitTSOP7000_Dec72018.pdf @@ -66,37 +64,29 @@ // Other examples may require a different treatment // This particular receiver also did receive lower frequencies but rather poorly and with a lower delay than usual // 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 // 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 - // 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 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 !!! - // IR messages are 16 bits long. Datalink messages have different lengths. // This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length // Header data with more than 16 bits is stored in decodedIRData.extra - // B&O is a pulse distance protocol, but it has 3 bit values 0, 1 and (equal/repeat) as well as a special start and trailing bit. // // MSB first, 4 start bits + 8 (to 16?) bit address + 8 bit command + 1 special trailing bit + 1 stop bit. // Address can be longer than 8 bit. - /* * Options for this decoder * @@ -119,18 +109,23 @@ #define BEO_UNIT 3125 // All timings are in microseconds -#define BEO_IR_MARK 200 // The length of a mark in the IR protocol +#define BEO_BIT_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 -#define BEO_PULSE_LENGTH_EQUAL (2 * BEO_UNIT) // 6250 The length of an equal bit -#define BEO_PULSE_LENGTH_ONE (3 * BEO_UNIT) // 9375 The length of a zero to one transition -#define BEO_PULSE_LENGTH_TRAILING_BIT (4 * BEO_UNIT) // 12500 The length of the stop bit -#define BEO_PULSE_LENGTH_START_BIT (5 * BEO_UNIT) // 15625 The length of the start bit +#define BEO_BIT_MARK_FOR_DECODE 250 +#define BEO_DATALINK_BIT_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol + +/* + * For all spaces really sent, the time of one bit mark (200 or 1562) is subtracted before the durations defined below + */ +#define BEO_ZERO_SPACE BEO_UNIT // 3125 +#define BEO_REPETITION_OF_PREVIOUS_BIT_SPACE (2 * BEO_UNIT) // 6250 The length of an repetition bit +#define BEO_ONE_SPACE (3 * BEO_UNIT) // 9375 +#define BEO_TRAILING_BIT_SPACE (4 * BEO_UNIT) // 12500 The length of the space of stop bit +#define BEO_START_BIT_SPACE (5 * BEO_UNIT) // 15625 +#define BEO_REPEAT_PERIOD 100000 // 100 ms - Not used yet + // It is not allowed to send two ones or zeros, you must send a one or zero and a equal instead. /************************************ @@ -175,41 +170,41 @@ void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBack // AGC / Start - 3 bits + first constant 0 header bit described in the official documentation if (!aBackToBack) { - mark(BEO_IR_MARK); + mark(BEO_BIT_MARK); } - space(BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK); - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK); - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK); + space(BEO_ZERO_SPACE - BEO_BIT_MARK); + mark(BEO_BIT_MARK); + space(BEO_ZERO_SPACE - BEO_BIT_MARK); + mark(BEO_BIT_MARK); + space(BEO_START_BIT_SPACE - BEO_BIT_MARK); // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions. // So this first 0 is treated as the last bit of AGC - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK); + mark(BEO_BIT_MARK); + space(BEO_ZERO_SPACE - BEO_BIT_MARK); bool tLastBitValueWasOne = false; // Send 8 (default) to 24 bit header and 8 bit data. uint32_t mask = 1UL << (aBits - 1); for (; mask; mask >>= 1) { if (tLastBitValueWasOne && !(aRawData & mask)) { - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_ZERO - BEO_IR_MARK); + mark(BEO_BIT_MARK); + space(BEO_ZERO_SPACE - BEO_BIT_MARK); tLastBitValueWasOne = false; } else if (!tLastBitValueWasOne && (aRawData & mask)) { - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_ONE - BEO_IR_MARK); + mark(BEO_BIT_MARK); + space(BEO_ONE_SPACE - BEO_BIT_MARK); tLastBitValueWasOne = true; } else { - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_EQUAL - BEO_IR_MARK); + mark(BEO_BIT_MARK); + space(BEO_REPETITION_OF_PREVIOUS_BIT_SPACE - BEO_BIT_MARK); } } // Stop - mark(BEO_IR_MARK); - space(BEO_PULSE_LENGTH_TRAILING_BIT - BEO_IR_MARK); - mark(BEO_IR_MARK); + mark(BEO_BIT_MARK); + space(BEO_TRAILING_BIT_SPACE - BEO_BIT_MARK); + mark(BEO_BIT_MARK); #else (void) aRawData; @@ -225,7 +220,7 @@ void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBack */ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bool aBackToBack, bool aUseDatalinkTiming) { #if defined(USE_NO_SEND_PWM) || BEO_KHZ == 38 // BEO_KHZ == 38 is for unit test which runs the B&O protocol with 38 kHz instead 0f 455 kHz - uint16_t tSendBEOMarkLength = aUseDatalinkTiming ? BEO_DATALINK_MARK : BEO_IR_MARK; + uint16_t tSendBEOMarkLength = aUseDatalinkTiming ? BEO_DATALINK_BIT_MARK : BEO_BIT_MARK; /* * 455 kHz PWM is currently not supported, maximum is 180 kHz @@ -238,16 +233,16 @@ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bo if (!aBackToBack) { mark(tSendBEOMarkLength); } - space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength); + space(BEO_ZERO_SPACE - tSendBEOMarkLength); mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength); + space(BEO_ZERO_SPACE - tSendBEOMarkLength); mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_START_BIT - tSendBEOMarkLength); + space(BEO_START_BIT_SPACE - tSendBEOMarkLength); // First bit of header is assumed to be a constant 0 to have a fixed state to begin with the equal decisions. // So this first 0 is treated as the last bit of AGC mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength); + space(BEO_ZERO_SPACE - tSendBEOMarkLength); bool tLastBitValueWasOne = false; // Header / Data @@ -255,21 +250,21 @@ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bo for (; mask; mask >>= 1) { if (tLastBitValueWasOne && !(aRawData & mask)) { mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_ZERO - tSendBEOMarkLength); + space(BEO_ZERO_SPACE - tSendBEOMarkLength); tLastBitValueWasOne = false; } else if (!tLastBitValueWasOne && (aRawData & mask)) { mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_ONE - tSendBEOMarkLength); + space(BEO_ONE_SPACE - tSendBEOMarkLength); tLastBitValueWasOne = true; } else { mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_EQUAL - tSendBEOMarkLength); + space(BEO_REPETITION_OF_PREVIOUS_BIT_SPACE - tSendBEOMarkLength); } } // Stop mark(tSendBEOMarkLength); - space(BEO_PULSE_LENGTH_TRAILING_BIT - tSendBEOMarkLength); + space(BEO_TRAILING_BIT_SPACE - tSendBEOMarkLength); mark(tSendBEOMarkLength); #else @@ -280,7 +275,7 @@ void IRsend::sendBangOlufsenRawDataLink(uint64_t aRawData, int_fast8_t aBits, bo #endif } -#define BEO_MATCH_DELTA (BEO_UNIT / 2 - MICROS_PER_TICK) +#define BEO_MATCH_DELTA (BEO_UNIT / 2 - MICROS_PER_TICK) // use a bigger margin for match than regular matching function static bool matchBeoLength(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { const uint16_t tMeasuredMicros = aMeasuredTicks * MICROS_PER_TICK; return aMatchValueMicros - BEO_MATCH_DELTA < tMeasuredMicros && tMeasuredMicros < aMatchValueMicros + BEO_MATCH_DELTA; @@ -302,7 +297,7 @@ bool IRrecv::decodeBangOlufsen() { } #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) - uint16_t protocolMarkLength = 0; // contains BEO_IR_MARK or BEO_DATALINK_MARK depending of 4. mark received + uint16_t protocolMarkLength = 0; // contains BEO_BIT_MARK or BEO_DATALINK_BIT_MARK depending of 4. mark received uint64_t tDecodedRawData = 0; #else uint32_t tDecodedRawData = 0; @@ -321,9 +316,9 @@ 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(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))) { + if ((matchMark(irparams.rawbuf[3], BEO_BIT_MARK_FOR_DECODE) || matchMark(irparams.rawbuf[3], BEO_DATALINK_BIT_MARK)) + && (matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_BIT_MARK_FOR_DECODE) + || matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_DATALINK_BIT_MARK))) { TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected")); } else { return false; // no B&O protocol @@ -332,18 +327,18 @@ bool IRrecv::decodeBangOlufsen() { /* * Check if leading gap is trailing bit of first AGC frame */ - if (!matchSpace(decodedIRData.initialGapTicks, BEO_PULSE_LENGTH_START_BIT)) { + if (!matchSpace(decodedIRData.initialGapTicks, BEO_START_BIT_SPACE)) { TRACE_PRINT(F("B&O: Leading gap of ")); // Leading gap is trailing bit of first frame TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); // Leading gap is trailing bit of first frame TRACE_PRINTLN(F(" us is wrong")); // Leading gap is trailing bit of first frame return false; // no B&O protocol } - if (matchMark(irparams.rawbuf[1], BEO_IR_MARK_FOR_DECODE)) { + if (matchMark(irparams.rawbuf[1], BEO_BIT_MARK_FOR_DECODE)) { # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) - protocolMarkLength = BEO_IR_MARK_FOR_DECODE; - } else if (matchMark(irparams.rawbuf[1], BEO_DATALINK_MARK)) { - protocolMarkLength = BEO_DATALINK_MARK; + protocolMarkLength = BEO_BIT_MARK_FOR_DECODE; + } else if (matchMark(irparams.rawbuf[1], BEO_DATALINK_BIT_MARK)) { + protocolMarkLength = BEO_DATALINK_BIT_MARK; # endif } else { TRACE_PRINTLN(F("B&O: mark length is wrong")); @@ -376,17 +371,17 @@ bool IRrecv::decodeBangOlufsen() { if (tPulseNumber < 4) { if (tPulseNumber < 2) { // bit 0 and 1 - if (matchSpace(spaceLength, BEO_PULSE_LENGTH_START_BIT - BEO_IR_MARK_FOR_DECODE)) { + if (matchSpace(spaceLength, BEO_START_BIT_SPACE - BEO_BIT_MARK_FOR_DECODE)) { TRACE_PRINTLN(F(": detected long start bit -> synchronize state now")); tPulseNumber = 2; } } else { if (tPulseNumber == 3) { - if (matchMark(markLength, BEO_IR_MARK_FOR_DECODE)) { + if (matchMark(markLength, BEO_BIT_MARK_FOR_DECODE)) { # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) - protocolMarkLength = BEO_IR_MARK_FOR_DECODE; - } else if (matchMark(markLength, BEO_DATALINK_MARK)) { - protocolMarkLength = BEO_DATALINK_MARK; + protocolMarkLength = BEO_BIT_MARK_FOR_DECODE; + } else if (matchMark(markLength, BEO_DATALINK_BIT_MARK)) { + protocolMarkLength = BEO_DATALINK_BIT_MARK; # endif } else { DEBUG_PRINTLN(F("B&O: 4. (start) mark length is wrong")); @@ -395,7 +390,7 @@ bool IRrecv::decodeBangOlufsen() { } // bit 2 and 3 if (!matchBeoLength(markLength + spaceLength, - (tPulseNumber == 2) ? BEO_PULSE_LENGTH_START_BIT : BEO_PULSE_LENGTH_ZERO)) { + (tPulseNumber == 2) ? BEO_START_BIT_SPACE : BEO_ZERO_SPACE)) { DEBUG_PRINTLN(F("B&O: Start length is wrong")); return false; } @@ -410,7 +405,7 @@ bool IRrecv::decodeBangOlufsen() { #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) if (!matchMark(markLength, protocolMarkLength)) { #else - if (!matchMark(markLength, BEO_IR_MARK_FOR_DECODE)) { + if (!matchMark(markLength, BEO_BIT_MARK_FOR_DECODE)) { #endif DEBUG_PRINTLN(F("B&O: Mark length is wrong")); return false; @@ -420,7 +415,7 @@ bool IRrecv::decodeBangOlufsen() { * Check for stop after receiving at least 8 bits for data and 4 bits for header */ if (tBitNumber > BEO_DATA_BITS + 4) { - if (matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_TRAILING_BIT)) { + if (matchBeoLength(markLength + spaceLength, BEO_TRAILING_BIT_SPACE)) { DEBUG_PRINTLN(F("B&O: Trailing bit detected")); break; } @@ -435,11 +430,11 @@ bool IRrecv::decodeBangOlufsen() { /* * Decode bit */ - if (tLastDecodedBitValue == 0 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ONE)) { + if (tLastDecodedBitValue == 0 && matchBeoLength(markLength + spaceLength, BEO_ONE_SPACE)) { tLastDecodedBitValue = 1; - } else if (tLastDecodedBitValue == 1 && matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_ZERO)) { + } else if (tLastDecodedBitValue == 1 && matchBeoLength(markLength + spaceLength, BEO_ZERO_SPACE)) { tLastDecodedBitValue = 0; - } else if (!matchBeoLength(markLength + spaceLength, BEO_PULSE_LENGTH_EQUAL)) { + } else if (!matchBeoLength(markLength + spaceLength, BEO_REPETITION_OF_PREVIOUS_BIT_SPACE)) { DEBUG_PRINT(F("B&O: Index=")); DEBUG_PRINT(tRawBufferMarkIndex); DEBUG_PRINT(F(" Length ")); diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index d0ea64ad7..ca64000db 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -367,7 +367,7 @@ bool IRrecv::decodeDistanceWidth() { Serial.println(tSpaceTicksShort * MICROS_PER_TICK); #endif - uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / BITS_IN_RAW_DATA_TYPE; + uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE; /* * We can have the following protocol timings @@ -398,8 +398,8 @@ bool IRrecv::decodeDistanceWidth() { /* * Decode in 32/64 bit chunks. Only the last chunk can contain less than 32/64 bits */ - if (tNumberOfBitsForOneDecode > BITS_IN_RAW_DATA_TYPE) { - tNumberOfBitsForOneDecode = BITS_IN_RAW_DATA_TYPE; + if (tNumberOfBitsForOneDecode > BITS_IN_DECODED_RAW_DATA_TYPE) { + tNumberOfBitsForOneDecode = BITS_IN_DECODED_RAW_DATA_TYPE; } if (tSpaceTicksLong > 0) { /* @@ -454,8 +454,8 @@ bool IRrecv::decodeDistanceWidth() { // fill array with decoded data decodedIRData.decodedRawDataArray[i] = decodedIRData.decodedRawData; - tStartIndex += (2 * BITS_IN_RAW_DATA_TYPE); - tNumberOfBits -= BITS_IN_RAW_DATA_TYPE; + tStartIndex += (2 * BITS_IN_DECODED_RAW_DATA_TYPE); + tNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE; } #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) diff --git a/src/ir_Kaseikyo.hpp b/src/ir_Kaseikyo.hpp index 3e0fb3c86..5fa32fcd6 100644 --- a/src/ir_Kaseikyo.hpp +++ b/src/ir_Kaseikyo.hpp @@ -141,7 +141,7 @@ void IRsend::sendKaseikyo(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumb tSendValue.UWord.LowWord = (aAddress << KASEIKYO_VENDOR_ID_PARITY_BITS) | tVendorParity; // set low nibble with vendor parity tSendValue.UBytes[2] = aCommand; tSendValue.UBytes[3] = aCommand ^ tSendValue.UBytes[0] ^ tSendValue.UBytes[1]; // 8 bit parity of 3 bytes command, address and vendor parity - IRRawDataType tRawKaseikyoData[2]; + IRDecodedRawDataType tRawKaseikyoData[2]; tRawKaseikyoData[0] = (uint32_t) tSendValue.UWord.LowWord << 16 | aVendorCode; // LSB of tRawKaseikyoData[0] is sent first tRawKaseikyoData[1] = tSendValue.UWord.HighWord; sendPulseDistanceWidthFromArray_P(&KaseikyoProtocolConstants, &tRawKaseikyoData[0], KASEIKYO_BITS, aNumberOfRepeats); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 61369232c..e47b4f9a7 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -79,7 +79,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only // https://en.wikipedia.org/wiki/RC-5 // mark->space => 0 // space->mark => 1 -// MSB first, 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command, no stop bit +// MSB first, 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command, no stop bit 14 bits incl. field bit and start bit // Field bit is 1 for RC5 and 0 (=inverted 7. command bit) for RC5X. That way the first 64 commands of RC5X are indistinguishable from RC5. // SF TAAA AACC CCCC // IR duty factor is 25% @@ -87,7 +87,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only // MARANTZ // https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended // Marantz uses RC5X and adds a a pause after the address / first 8 bits -// After the 6 bit command another 6 bit command extension is sent +// After the 6 bit command (of RC5) an additional 6 bit command extension is sent -> 20 bits incl. field bit and start bit // #define RC5_ADDRESS_BITS 5 #define RC5_COMMAND_BITS 6 @@ -482,7 +482,7 @@ bool IRrecv::decodeRC5() { + 500,- 900 +1000,- 350 + 550,- 850 + 500 Duration=37450us */ -// Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit +// Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit and constant bit 1 // Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits + 2666us pause - 37 bits incl. start bit // !!! toggle bit has double timing !!! // mark->space => 1 - Inverse of RC5! From 1d872185c3a00c1c7e1e18163c1df76cc27162e3 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 27 Feb 2026 09:06:06 +0100 Subject: [PATCH 119/133] Closes #1347 Bug in sendRC5() - toggle bit is never set if autorepeat is not enabled --- src/IRremoteInt.h | 1 + src/ir_RC5_RC6.hpp | 39 +++++++++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 8cbba57dd..12805d1d9 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -650,6 +650,7 @@ class IRsend { void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first + void setRC5ToggleBitValue(uint8_t aRC5ToggleBitValue); void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true); void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aMarantzExtension, bool aEnableAutomaticToggle = true); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index e47b4f9a7..58b9d9747 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -117,6 +117,15 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only * Start of send and decode functions ************************************/ +/* + * Just in case to permanently send it as 0 because start value is 1, + * or to reset toggle bit after a transmission with automatic toggling. + * @param aRC5ToggleBitValue 0 or 1, only LSB is taken + */ +void IRsend::setRC5ToggleBitValue(uint8_t aRC5ToggleBitValue){ + sLastSendToggleValue = aRC5ToggleBitValue & 0x01; +} + /** * !!! Not tested, because no Marantz remote was at hand and no receive function was contributed!!! * Send function for the Marantz version of RC5(X) with a pause of 4 * RC5_UNIT after address / first 8 bits @@ -153,13 +162,13 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNum tIRExtData |= (aMarantzExtension & 0x3F); if (aEnableAutomaticToggle) { - if (sLastSendToggleValue == 0) { - sLastSendToggleValue = 1; - // set toggled bit - tIRData |= 1 << (RC5_ADDRESS_BITS); - } else { - sLastSendToggleValue = 0; - } + // invert toggle bit if enabled + sLastSendToggleValue ^= 1; + } + + // set toggled bit independent of current state of aEnableAutomaticToggle + if (sLastSendToggleValue) { + tIRData |= 1 << RC5_ADDRESS_BITS; } uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -206,14 +215,15 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe } tIRData |= aCommand; + if (aEnableAutomaticToggle) { - if (sLastSendToggleValue == 0) { - sLastSendToggleValue = 1; - // set toggled bit - tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS); - } else { - sLastSendToggleValue = 0; - } + // invert toggle bit if enabled + sLastSendToggleValue ^= 1; + } + + // set toggled bit independent of current state of aEnableAutomaticToggle + if (sLastSendToggleValue) { + tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS); } uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; @@ -857,6 +867,7 @@ void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) { // Toggle bit static int toggleBit = 1; if (toggle) { + // invert static toggle bit if (toggleBit == 0) { toggleBit = 1; } else { From 69d36199d606ab56de1f0f990f2b01f416a9cc9f Mon Sep 17 00:00:00 2001 From: ArminJo Date: Fri, 27 Feb 2026 19:49:21 +0100 Subject: [PATCH 120/133] Bumped version to 4.6.1 --- Contributors.md | 1 + changelog.md | 4 ++++ examples/UnitTest/UnitTest.ino | 2 +- library.json | 2 +- library.properties | 2 +- src/IRVersion.h | 4 ++-- src/IRremoteInt.h | 2 +- src/ir_RC5_RC6.hpp | 32 ++++++++++++++------------------ 8 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Contributors.md b/Contributors.md index 94ad676a8..033dba251 100644 --- a/Contributors.md +++ b/Contributors.md @@ -37,5 +37,6 @@ These are the active contributors of this project that you may contact if there - [A.R.Jung](https://github.com/arjung467) Marantz-RC5 extension support #1314. - [silen72](https://github.com/silen72) Fixing ESP32 multiple attach bug #1324. - [danielweidman](https://github.com/danielweidman) Adding OpenLASIR protocol. +- [Craig Leres](https://github.com/leres) Found bug #1347 in RC5/RC6 autorepeat bit handling. Note: Please let [ArminJo](https://github.com/ArminJo) know if you have been missed. diff --git a/changelog.md b/changelog.md index c6cdc461d..4827c0686 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.6.1 +- Fixed bug #1347 in RC5/RC6 autorepeat bit handling. Thanks to Craig Leres. +- Added function `setToggleBitValueForRC5AndRC6()`. + # 4.6.0 - Fixed missing ESP IRAM_ATTR for receiving interrupt. - Changed `USE_DEFAULT_FEEDBACK_LED_PIN` from 0 to 0xFF, because megaTinyCore defines the not special pin PIN_PA4 as 0. diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index e2f428c83..4431b09e4 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -940,7 +940,7 @@ void loop() { #if defined(DECODE_RC6) Serial.println(F("Send RC6")); Serial.flush(); - sLastSendToggleValue = sAddress & 0x01; // to modify toggling at each loop + IrSender.setToggleBitValueForRC5AndRC6(sAddress); // To modify start value of toggling for each loop. Only LSB is taken :-). IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true); checkReceive(sAddress & 0xFF, sCommand); diff --git a/library.json b/library.json index 18db09a0b..579676110 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.6.0", + "version": "4.6.1", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index 0289b475f..62bb65d9b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.6.0 +version=4.6.1 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRVersion.h b/src/IRVersion.h index ebdc8f770..d538211d3 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.6.0" +#define VERSION_IRREMOTE "4.6.1" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 6 -#define VERSION_IRREMOTE_PATCH 0 +#define VERSION_IRREMOTE_PATCH 1 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 12805d1d9..e155fe02f 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -650,7 +650,7 @@ class IRsend { void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first - void setRC5ToggleBitValue(uint8_t aRC5ToggleBitValue); + void setToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue); void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true); void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aMarantzExtension, bool aEnableAutomaticToggle = true); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 58b9d9747..68fd08ac5 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -122,7 +122,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only * or to reset toggle bit after a transmission with automatic toggling. * @param aRC5ToggleBitValue 0 or 1, only LSB is taken */ -void IRsend::setRC5ToggleBitValue(uint8_t aRC5ToggleBitValue){ +void IRsend::setToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue) { sLastSendToggleValue = aRC5ToggleBitValue & 0x01; } @@ -165,7 +165,6 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNum // invert toggle bit if enabled sLastSendToggleValue ^= 1; } - // set toggled bit independent of current state of aEnableAutomaticToggle if (sLastSendToggleValue) { tIRData |= 1 << RC5_ADDRESS_BITS; @@ -215,12 +214,10 @@ void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe } tIRData |= aCommand; - if (aEnableAutomaticToggle) { // invert toggle bit if enabled sLastSendToggleValue ^= 1; } - // set toggled bit independent of current state of aEnableAutomaticToggle if (sLastSendToggleValue) { tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS); @@ -605,14 +602,14 @@ void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRe tIRRawData.UByte.MidLowByte = aAddress; tIRRawData.UWord.HighWord = 0; // must clear high word for the 3 mode bits to be 0 + if (aEnableAutomaticToggle) { - if (sLastSendToggleValue == 0) { - sLastSendToggleValue = 1; - // set toggle bit - tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0 - } else { - sLastSendToggleValue = 0; - } + // invert toggle bit if enabled + sLastSendToggleValue ^= 1; + } + // set toggled bit independent of current state of aEnableAutomaticToggle + if (sLastSendToggleValue) { + tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0 } DEBUG_PRINT(F("RC6: ToggleValue=")); @@ -650,13 +647,12 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR tIRRawData.UWord.HighWord = aCustomer | 0x400; // bit 31 is always 1 if (aEnableAutomaticToggle) { - if (sLastSendToggleValue == 0) { - sLastSendToggleValue = 1; - // set toggled bit - tIRRawData.UByte.HighByte |= 0x80; // toggle bit is bit 32 - } else { - sLastSendToggleValue = 0; - } + // invert toggle bit if enabled + sLastSendToggleValue ^= 1; + } + // set toggled bit independent of current state of aEnableAutomaticToggle + if (sLastSendToggleValue) { + tIRRawData.UByte.HighByte |= 0x80; // toggle bit is bit 32 } // Set mode bits From 61465c87ed362f5dbc96f2c05124b4ced1602cd6 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 2 Mar 2026 22:26:07 +0100 Subject: [PATCH 121/133] Added removed typedef `IRRawDataType` for backward compatibility. --- changelog.md | 4 ++++ src/IRremoteInt.h | 2 ++ src/ir_LG.hpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 4827c0686..3943cf16f 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,9 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.6.2 +- Added removed typedef `IRRawDataType` for backward compatibility. + # 4.6.1 - Fixed bug #1347 in RC5/RC6 autorepeat bit handling. Thanks to Craig Leres. - Added function `setToggleBitValueForRC5AndRC6()`. @@ -18,6 +21,7 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I - Improved biphase decoding. - Improved debug output handling. - Moved `IRCommandDispatcher` from demo to main library folder. +- Changed `IRRawDataType` to `IRDecodedRawDataType`. # 4.5.0 - does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt. - Added support for **multiple receiver instances**. diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index e155fe02f..02f904acf 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -154,6 +154,8 @@ typedef uint32_t IRDecodedRawDataType; typedef uint64_t IRDecodedRawDataType; #define BITS_IN_DECODED_RAW_DATA_TYPE 64 #endif +typedef IRDecodedRawDataType IRRawDataType; // Define old IRRawDataType (removed in 4.6.0) for backward compatibility + #define DECODED_RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_DECODED_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. diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 12724b04c..1c7c37237 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -63,7 +63,7 @@ // see: https://www.mikrocontroller.net/articles/IRMP_-_english#LGAIR // MSB first, 1 start bit + 8 bit address + 16 bit command + 4 bit checksum + 1 stop bit (28 data bits). // Bit and repeat timing is like NEC -// LG2 has different header timing and a shorter bit time +// LG2 has different header timing and a shorter bit time than LG /* * LG remote IR-LED measurements: Type AKB 73315611 for air conditioner, Ver1.1 from 2011.03.01 * Protocol: LG2 From 4bc10750af258d14ab27a2493fab3e54a22d625c Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 4 Mar 2026 11:45:01 +0100 Subject: [PATCH 122/133] Bumped version to 4.6.2 --- README.md | 221 +++++++++++++++++++++-------------------- library.json | 2 +- library.properties | 2 +- src/IRReceive.hpp | 6 +- src/IRVersion.h | 4 +- src/ir_BangOlufsen.hpp | 2 +- 6 files changed, 120 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 1de92f91b..bad7b5b81 100644 --- a/README.md +++ b/README.md @@ -57,25 +57,26 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [Protocol=PULSE_DISTANCE](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolpulse_distance) * [Protocol=UNKNOWN](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#protocolunknown) * [How to deal with protocols not supported by IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#how-to-deal-with-protocols-not-supported-by-irremote) + * [Multiple IR receivers](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receivers) - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) * [Sending UNKNOWN protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-unknown-protocol) * [Sending IRDB IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-irdb-ir-codes) + + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) + * [Flipper Zero Codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#flipper-zero-codes) * [Send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#send-pin) * [Polarity of send pin](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#polarity-of-send-pin) - + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) + * [Simulate an IR receiver module for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module-for-sending) + * [Increase strength of sent output signal](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#increase-strength-of-sent-output-signal) + * [Multiple IR sender instances](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-sender-instances) - [Tiny NEC receiver and sender](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) -- [IRCommandDispatcher class](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ircommanddispatcher-class) - [The FAST protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#the-fast-protocol) - [Feedback LED](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#feedback-led) +- [IRCommandDispatcher class](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#ircommanddispatcher-class) - [FAQ and hints](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#faq-and-hints) * [Receiving stops after analogWrite() or tone() or after running a motor](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-stops-after-analogwrite-or-tone-or-after-running-a-motor) * [Receiving sets overflow flag](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#receiving-sets-overflow-flag) * [Problems with Neopixels, FastLed etc.](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#problems-with-neopixels-fastled-etc) * [Does not work/compile with another library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#does-not-workcompile-with-another-library) - * [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) - * [Simulate an IR receiver module for sending](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#simulate-an-ir-receiver-module-for-sending) * [Minimal CPU clock frequency](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-cpu-clock-frequency) * [Bang & Olufsen protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#bang--olufsen-protocol) - [Examples for this library](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#examples-for-this-library) @@ -319,7 +320,7 @@ If this doesn't work for you, you can be sure that 4.x is trying to be compatibl In the Arduino IDE the calls are executed when you click on *Verify* or *Upload*. And now **our problem with Arduino** is:
-**How to set [compile options](#compile-options--macros-for-this-library) for all *.cpp files, especially for libraries used?**
+**How to set [compile options](#compile-options--macros-for-irremote) for all *.cpp files, especially for libraries used?**
IDE's like [Sloeber](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-sloeber-ide) or [PlatformIO](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#modifying-compile-options--macros-with-platformio) support this by allowing to specify a set of options per project. They add these options at each compiler call e.g. `-DTRACE`. @@ -335,7 +336,7 @@ Therefore, using the **.cpp** extension is no longer possible. One solution is t 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, +In order to support [compile options](#compile-options--macros-for-irremote) more easily, you **must** use the statement `#include ` instead of `#include ` in your main program (aka *.ino file with setup() and loop()). In **all other files** you must use the following, to **prevent `multiple definitions` linker errors**: @@ -579,6 +580,18 @@ If you do not know which protocol your IR transmitter uses, you have several cho It can automatically generate a send sketch for your protocol by exporting as "Arduino Raw". It supports IRremote, the old [IRLib](https://github.com/cyborg5/IRLib) and [Infrared4Arduino](https://github.com/bengtmartensson/Infrared4Arduino). +## Multiple IR receivers +**This library now supports multiple IR receiver instances (IRrecv) per CPU** by activating `SUPPORT_MULTIPLE_RECEIVER_INSTANCES` +and providing the simple function `UserIRReceiveTimerInterruptHandler()`. +See the [MultipleReceivers example](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/MultipleReceivers/MultipleReceivers.ino). + +There is also another way to use multiple receivers. +You can connect the output pins of each IR receiver to one input pin. +Then you can use the standard receiver object (IrReceiver). +The IR receiver modules internally use an NPN transistor as output device with just a 30k resistor to VCC. +This is basically an "open collector" and allows multiple output pins to be connected to one Arduino input pin.
+However, keep in mind that any weak / disturbed signal from one of the receivers will also interfere with a good signal from another receiver. +
# Sending IR codes @@ -612,9 +625,6 @@ like done in [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blo 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 -> 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 @@ -622,6 +632,20 @@ like e.g. `IrSender.sendNEC((device << 8) | subdevice, 0x19, 2)`.
An **exact mapping** can be found in the [IRP definition files for IR protocols](https://github.com/probonopd/MakeHex/tree/master/protocols). "D" and "S" denotes device and subdevice and "F" denotes the function. +### List of public IR code databases +http://www.harctoolbox.org/IR-resources.html + +## Flipper Zero codes +The codes found in the [Flipper-IRDB database](https://github.com/Lucaslhm/Flipper-IRDB) are quite straightforward to convert, because the also use the address / command scheme.
+Protocol matching is NECext -> Onkyo, Samsung32 -> Samsung, SIRC20 -> Sony with 20 bits etc. + +| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) | +|-|-| +| Samsung32 | Samsung | +| NEC | NEC | +| NECext | ONKYO | +| [\\\\\\\\\](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)
and ID is MSB of address.
address: 8A 02 20 00
command: 56 03 00 00
-> **IRremote:**
Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \\\\\\\ | + ## Send pin Any pin can be chosen as send pin as long as `IR_SEND_PIN` is **not** defined. This is because the PWM signal is generated by default with software bit banging, since `SEND_PWM_BY_TIMER` is not active.
@@ -636,79 +660,22 @@ 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 - -## Flipper Zero -[Flipper IRDB Database](https://github.com/Lucaslhm/Flipper-IRDB) - -| [Flipper decoding](https://github.com/flipperdevices/flipperzero-firmware/tree/release/lib/infrared/encoder_decoder) | [IRremote decoding](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src) | -|-|-| -| Samsung32 | Samsung | -| NEC | NEC | -| NECext | ONKYO | -| [\\\\\\\\\](https://github.com/flipperdevices/flipperzero-firmware/blob/027ea9ea36da137144548295c016d99255af53c3/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c#L26)
and ID is MSB of address.
address: 8A 02 20 00
command: 56 03 00 00
-> **IRremote:**
Address 0x6A8, sendPanasonic (for 02 20) and Command 0x35 | \\\\\\\ | - -
- -# IRCommandDispatcher class -If you want to **handle many IR commands** in a structured way, you can use a big **switch statement**, or use the class `IRCommandDispatcher`.
-The IRCommandDispatcher class receives IR commands and maps them to different functions by means of a mapping array `IRMapping[]`. - -By default, every mapped command is **blocking**. However it can be declared as **non-blocking** and / or **repeatable**.
-Non-blocking commands are executed immediately, blocking commands are executed if no other command is just running. -If another blocking command is currently running, a **request to stop** is set -and the command is stored for the main loop to be executed by `checkAndRunSuspendedBlockingCommands()`. -The request to stop must be checked by any blocking function using the macros `DELAY_AND_RETURN_IF_STOP()`, `RETURN_IF_STOP`, `BREAK_IF_STOP` and `IS_STOP_REQUESTED`.
-Only commands that are marked as **repeatable** will be exectuted when a IR repeat frame is received. -Therefore this only makes sense for non-blocking comands :-). - -Code snippets are from [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo). - -```c++ -// IR code mapping which is useful if more than one remote is supported -#define IR_0 0x19 -#define IR_HASH 0x0D -#define COMMAND_BLINK IR_0 -#define COMMAND_STOP IR_HASH - -// Strings of commands for Serial output -static const char blink20times[] PROGMEM ="blink 20 times"; -static const char stop[] PROGMEM ="stop"; +## Simulate an IR receiver module for sending +To simulate an IR receiver (such as the TSOP1738) which provides an active-low output, you only need to enable the `USE_NO_SEND_PWM` macro. +In the case you must simulate exotic IR receivers, which provides an active-high output, you also need to enable the `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` macro. -/* - * Main mapping array of commands to C functions and command strings - * The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled - */ -const struct IRToCommandMappingStruct IRMapping[] = { -{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, -{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, -/* - * Short commands that can always be executed - */ -{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 }, -... -/* - * Repeatable short commands - */ -{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, -... +## Increase strength of sent output signal +**The best way to increase the IR power for free** is to use 2 or 3 IR diodes in series. One diode requires 1.2 volt at 20 mA or 1.5 volt at 100 mA so you can supply up to 3 diodes with a 5 volt output.
+To power **2 diodes** with 1.2 V and 20 mA and a 5 V supply, set the resistor to: (5 V - 2.4 V) -> 2.6 V / 20 mA = **130 Ω**.
+For **3 diodes** it requires 1.4 V / 20 mA = **70 Ω**.
+The actual current might be lower since of **loss at the AVR pin**. E.g. 0.3 V at 20 mA.
+If you do not require more current than 20 mA, there is no need to use an external transistor (at least for AVR chips). -/* - * This is a blocking function which checks for stop - */ -void doLedBlink20times() { - for (int i = 0; i < 20; ++i) { - digitalWrite(LED_BUILTIN, HIGH); - DELAY_AND_RETURN_IF_STOP(200); - digitalWrite(LED_BUILTIN, LOW); - DELAY_AND_RETURN_IF_STOP(200); - } -} -// Other useful macros are RETURN_IF_STOP, BREAK_IF_STOP and IS_STOP_REQUESTED. -``` +On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:. -Examples of mapping arrays can be found in the [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/DemoIRCommandMapping.h#L185), for [QuadrupedControl](https://github.com/ArminJo/QuadrupedControl/blob/master/examples/QuadrupedControl/QuadrupedIRCommandMapping.h#L445), for [RobotArmControl](https://github.com/ArminJo/RobotArmControl/blob/master/RobotArmControl/RobotArmIRCommandMapping.h#L320) or for [4 WD RobotCar control](https://github.com/ArminJo/PWMMotorControl/blob/master/examples/IRDispatcherControl/RobotCarIRCommandMapping.h#L308)
+## 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.
@@ -817,6 +784,68 @@ The starting value is set by the second parameter of `begin(uint_fast8_t aReceiv LED feedback is **always enabled** when sending and cannot be deactivated programmatically. It can only be deactivated at compile time. +# IRCommandDispatcher class +If you want to **handle many IR commands** in a structured way, you can use a big **switch statement**, or use the class `IRCommandDispatcher`.
+The IRCommandDispatcher class receives IR commands and maps them to different functions by means of a mapping array `IRMapping[]`. + +By default, every mapped command is **blocking**. However it can be declared as **non-blocking** and / or **repeatable**.
+Non-blocking commands are executed immediately, blocking commands are executed if no other command is just running. +If another blocking command is currently running, a **request to stop** is set +and the command is stored for the main loop to be executed by `checkAndRunSuspendedBlockingCommands()`. +The request to stop must be checked by any blocking function using the macros `DELAY_AND_RETURN_IF_STOP()`, `RETURN_IF_STOP`, `BREAK_IF_STOP` and `IS_STOP_REQUESTED`.
+Only commands that are marked as **repeatable** will be exectuted when a IR repeat frame is received. +Therefore this only makes sense for non-blocking comands :-). + +Code snippets are from [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo). + +```c++ +// IR code mapping which is useful if more than one remote is supported +#define IR_0 0x19 +#define IR_HASH 0x0D +#define COMMAND_BLINK IR_0 +#define COMMAND_STOP IR_HASH + +// Strings of commands for Serial output +static const char blink20times[] PROGMEM ="blink 20 times"; +static const char stop[] PROGMEM ="stop"; + +/* + * Main mapping array of commands to C functions and command strings + * The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled + */ +const struct IRToCommandMappingStruct IRMapping[] = { +{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, +{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, +/* + * Short commands that can always be executed + */ +{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, tone1800 }, +... +/* + * Repeatable short commands + */ +{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, increaseBlink }, +... + +/* + * This is a blocking function which checks for stop + */ +void doLedBlink20times() { + for (int i = 0; i < 20; ++i) { + digitalWrite(LED_BUILTIN, HIGH); + DELAY_AND_RETURN_IF_STOP(200); + digitalWrite(LED_BUILTIN, LOW); + DELAY_AND_RETURN_IF_STOP(200); + } +} +// Other useful macros are RETURN_IF_STOP, BREAK_IF_STOP and IS_STOP_REQUESTED. +``` + +Examples of mapping arrays can be found in the [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/IRDispatcherDemo/DemoIRCommandMapping.h#L185), for [QuadrupedControl](https://github.com/ArminJo/QuadrupedControl/blob/master/examples/QuadrupedControl/QuadrupedIRCommandMapping.h#L445), for [RobotArmControl](https://github.com/ArminJo/RobotArmControl/blob/master/RobotArmControl/RobotArmIRCommandMapping.h#L320) or for [4 WD RobotCar control](https://github.com/ArminJo/PWMMotorControl/blob/master/examples/IRDispatcherControl/RobotCarIRCommandMapping.h#L308)
+ +
+ + # FAQ and hints ## Receiving stops after analogWrite() or tone() or after running a motor The receiver sample interval of 50 µs is generated by a timer. On many boards this must be a [hardware timer](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). @@ -849,34 +878,6 @@ There are some other solutions to this on **more powerful CPU's**, **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 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 Ω**.
-For **3 diodes** it requires 1.4 V / 20 mA = **70 Ω**.
-The actual current might be lower since of **loss at the AVR pin**. E.g. 0.3 V at 20 mA.
-If you do not require more current than 20 mA, there is no need to use an external transistor (at least for AVR chips). - -On my Arduino Nanos, I always use a 100 Ω series resistor and one IR LED :grinning:. - -## Simulate an IR receiver module for sending -To simulate an IR receiver (such as the TSOP1738) which provides an active-low output, you only need to enable the `USE_NO_SEND_PWM` macro. -In the case you must simulate exotic IR receivers, which provides an active-high output, you also need to enable the `USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM` macro. - ## 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 requires no polling, runs with 1 MHz.
@@ -887,7 +888,7 @@ You can switch to timer PWM generation by `#define SEND_PWM_BY_TIMER`. The Bang & Olufsen protocol decoder is not enabled by default, i.e if no protocol is enabled explicitly by #define `DECODE_`. It must always be enabled explicitly by `#define DECODE_BEO`. This is because it has an **IR transmit frequency of 455 kHz** and therefore requires a different receiver hardware (TSOP7000).
And because **generating a 455 kHz PWM signal is currently only implemented for `SEND_PWM_BY_TIMER`**, sending only works if `SEND_PWM_BY_TIMER` or `USE_NO_SEND_PWM` is defined.
-For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L44). +For more info, see [ir_BangOlufsen.hpp](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_BangOlufsen.hpp#L46). # Examples for this library These examples can be found in the Arduino IDE under File > Examples > Examples from Custom Libraries / IRremote.
diff --git a/library.json b/library.json index 579676110..b2e8660f4 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.6.1", + "version": "4.6.2", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index 62bb65d9b..cb8f0aec6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.6.1 +version=4.6.2 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 7e5265e27..b8ae36ed1 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -57,7 +57,9 @@ unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR wi IRrecv IrReceiver; /** - * Instantiate the IRrecv class. Multiple instantiation is not supported. + * Instantiate the IRrecv class. Multiple instantiation is supported by activating SUPPORT_MULTIPLE_RECEIVER_INSTANCES and providing + * the simple function UserIRReceiveTimerInterruptHandler(). This function is required, because we have only one timer resource. + * See the MultipleReceivers example. * @param IRReceivePin Arduino pin to use. No sanity check is made. */ IRrecv::IRrecv() { @@ -69,7 +71,7 @@ IRrecv::IRrecv(uint_fast8_t aReceivePin) { } /** - * Instantiate the IRrecv class. Multiple instantiation is not supported. + * Instantiate the IRrecv class. * @param aReceivePin Arduino pin to use, where a demodulating IR receiver is connected. * @param aFeedbackLEDPin if 0xFF, then take board specific LED_BUILTIN pin if it is defined as macro */ diff --git a/src/IRVersion.h b/src/IRVersion.h index d538211d3..f8ee19325 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.6.1" +#define VERSION_IRREMOTE "4.6.2" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 6 -#define VERSION_IRREMOTE_PATCH 1 +#define VERSION_IRREMOTE_PATCH 2 /* * Macro to convert 3 version parts into an integer diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 2716757f4..041004a7f 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -10,7 +10,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Daniel Wallner and Armin Joachimsmeyer + * Copyright (c) 2022-2026 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 From 5b033d8f59762ad5ae324e01c7fa3d03b13b4fab Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 8 Mar 2026 11:28:00 +0100 Subject: [PATCH 123/133] Documentation and UnitTest with TinyIRSender --- README.md | 15 ++-- .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 10 +-- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 7 +- examples/CallbackDemo/CallbackDemo.ino | 2 +- examples/CallbackDemo/PinDefinitionsAndMore.h | 7 +- examples/ControlRelay/ControlRelay.ino | 4 +- examples/ControlRelay/PinDefinitionsAndMore.h | 7 +- .../IRDispatcherDemo/IRDispatcherDemo.ino | 2 +- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 7 +- .../IRremoteExtensionClass.cpp | 6 +- .../IRremoteExtensionTest.ino | 8 ++- .../PinDefinitionsAndMore.h | 7 +- examples/MicroGirs/MicroGirs.ino | 8 ++- examples/MicroGirs/PinDefinitionsAndMore.h | 7 +- .../MultipleReceivers/MultipleReceivers.ino | 9 +-- .../MultipleReceivers/PinDefinitionsAndMore.h | 7 +- .../ReceiveAndSend/PinDefinitionsAndMore.h | 7 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 19 ++--- .../PinDefinitionsAndMore.h | 7 +- .../ReceiveAndSendDistanceWidth.ino | 14 ++-- .../PinDefinitionsAndMore.h | 7 +- .../ReceiveAndSendHob2Hood.ino | 2 +- examples/ReceiveDemo/PinDefinitionsAndMore.h | 7 +- examples/ReceiveDemo/ReceiveDemo.ino | 7 +- examples/ReceiveDump/PinDefinitionsAndMore.h | 7 +- examples/ReceiveDump/ReceiveDump.ino | 15 ++-- .../PinDefinitionsAndMore.h | 7 +- .../ReceiveOneAndSendMultiple.ino | 2 +- .../SendAndReceive/PinDefinitionsAndMore.h | 7 +- examples/SendAndReceive/SendAndReceive.ino | 2 +- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 7 +- .../SendBoseWaveDemo/SendBoseWaveDemo.ino | 2 +- examples/SendDemo/PinDefinitionsAndMore.h | 7 +- examples/SendDemo/SendDemo.ino | 21 +++--- .../PinDefinitionsAndMore.h | 7 +- .../SendLGAirConditionerDemo.ino | 2 +- .../SendProntoDemo/PinDefinitionsAndMore.h | 7 +- examples/SendProntoDemo/SendProntoDemo.ino | 2 +- examples/SendRawDemo/PinDefinitionsAndMore.h | 7 +- examples/SendRawDemo/SendRawDemo.ino | 2 +- .../SimpleReceiver/PinDefinitionsAndMore.h | 7 +- examples/SimpleReceiver/SimpleReceiver.ino | 5 +- .../PinDefinitionsAndMore.h | 7 +- .../SimpleReceiverForHashCodes.ino | 13 ++-- examples/SimpleSender/PinDefinitionsAndMore.h | 7 +- examples/SimpleSender/SimpleSender.ino | 7 +- examples/TinyReceiver/PinDefinitionsAndMore.h | 7 +- examples/TinyReceiver/TinyReceiver.ino | 3 +- examples/TinySender/PinDefinitionsAndMore.h | 7 +- examples/TinySender/TinySender.ino | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 7 +- examples/UnitTest/UnitTest.ino | 46 +++++++++---- examples/UnitTest/UnitTest.log | 69 ++++++++++++++++++- src/IRReceive.hpp | 18 +++-- src/IRremote.hpp | 12 ++-- src/IRremoteInt.h | 11 +-- src/TinyIRSender.hpp | 6 +- src/digitalWriteFast.h | 7 +- src/ir_DistanceWidthProtocol.hpp | 2 +- src/ir_FAST.hpp | 2 +- src/ir_NEC.hpp | 2 +- src/ir_OpenLASIR.hpp | 16 ++--- src/ir_RC5_RC6.hpp | 7 +- src/ir_Samsung.hpp | 4 +- src/private/IRTimer.hpp | 17 ++++- 65 files changed, 385 insertions(+), 193 deletions(-) diff --git a/README.md b/README.md index bad7b5b81..68661c518 100644 --- a/README.md +++ b/README.md @@ -699,6 +699,8 @@ However, **interrupts are explicitly enabled here** to allow the use of delay() Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`. +The **TinyIRSender** generates its 38 kHz signal by **[bit banging](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/TinyIRSender.hpp#L68)** using the `delayMicroseconds()` and `micros()` functions. + ### TinyIRReceiver usage ```c++ //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. @@ -728,7 +730,7 @@ void setup() { void loop() {} ``` -Another tiny receiver and sender **supporting more protocols** can be found [here](https://github.com/LuisMiCa/IRsmallDecoder). +Another tiny receiver **supporting more protocols** can be found [here](https://github.com/LuisMiCa/IRsmallDecoder). # The FAST protocol The FAST protocol is a proprietary modified JVC protocol **without address, with parity and with a shorter header**. @@ -880,9 +882,14 @@ This is often due to **timer resource conflicts** with the other library. Please ## 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 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`. +The TinyReceiver, which requires no polling, works down to 1 MHz.
+For sending, the **minimal CPU clock frequency for software generated PWM is 8 MHz**. +You can switch to timer and hardware PWM generation at fixed pins by `#define SEND_PWM_BY_TIMER`. +### Hardware PWM generation of sending signal with 8 bit timer +- 16 MHZ F_CPU and 38 kHz -> prescaling = 2, divider = 210.526 -> 38.1 kHz with divider 210 +- 8 MHZ F_CPU and 38 kHz -> no prescaling , divider = 210.526 -> 38.1 kHz with divider 210 +- 4 MHZ F_CPU and 38 kHz -> no prescaling , divider = 105.26 -> 38.1 kHz with divider 105 +- 1 MHZ F_CPU and 38 kHz -> no prescaling , divider = 26.31 -> 38.4 kHz with divider 36 ## 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`. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index 02758ea51..bf86a092e 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -33,17 +33,19 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less #define RAW_BUFFER_LENGTH 360 # else +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif -# if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +# if RAMSIZE <= 0x800 #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds # else #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 400 // The decoder accepts mark or space durations up to 400 * 50 (MICROS_PER_TICK) = 20 milliseconds diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/CallbackDemo/CallbackDemo.ino b/examples/CallbackDemo/CallbackDemo.ino index 60ffe771a..bd348d14e 100644 --- a/examples/CallbackDemo/CallbackDemo.ino +++ b/examples/CallbackDemo/CallbackDemo.ino @@ -64,7 +64,7 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include /* diff --git a/examples/CallbackDemo/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/CallbackDemo/PinDefinitionsAndMore.h +++ b/examples/CallbackDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ControlRelay/ControlRelay.ino b/examples/ControlRelay/ControlRelay.ino index 0ea2e73aa..a475c6771 100644 --- a/examples/ControlRelay/ControlRelay.ino +++ b/examples/ControlRelay/ControlRelay.ino @@ -33,9 +33,9 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. -#if FLASHEND <= 0x1FFF || (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167 +#if FLASHEND <= 0x1FFF || RAMSIZE <= 0x400 // For 8k flash or 512 bytes RAM or less, like ATtiny85, ATtiny167 #define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. #define EXCLUDE_EXOTIC_PROTOCOLS #endif diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index b9a0194ee..81ddf02af 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -37,7 +37,7 @@ #define INFO // To see some informative output of the IRCommandDispatcher library //#define DEBUG // To see some additional debug output of the IRCommandDispatcher library -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #if defined(INFO) || defined(DEBUG) #define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries. diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 9f1a73401..587263de9 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -36,10 +36,12 @@ * 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 may require up to 750. Default is 200. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less #define RAW_BUFFER_LENGTH 360 # else +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino index 50bea009f..9ee1e437b 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino +++ b/examples/IRremoteExtensionTest/IRremoteExtensionTest.ino @@ -30,13 +30,15 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less #define RAW_BUFFER_LENGTH 360 # else +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/MicroGirs/MicroGirs.ino b/examples/MicroGirs/MicroGirs.ino index 194728d32..7af892c10 100644 --- a/examples/MicroGirs/MicroGirs.ino +++ b/examples/MicroGirs/MicroGirs.ino @@ -64,13 +64,15 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less #define RAW_BUFFER_LENGTH 360 # else +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index 3340d0fe9..d1cc9e1d1 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2025 Armin Joachimsmeyer + * Copyright (c) 2025-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -62,10 +62,7 @@ #define SUPPORT_MULTIPLE_RECEIVER_INSTANCES void UserIRReceiveTimerInterruptHandler(); // Is defined below and must be declared 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 "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include // include the library IRrecv MySecondIrReceiver(IR_RECEIVE_PIN_OF_SECOND_RECEIVER); // This sets the pin for the second instance @@ -144,7 +141,7 @@ void handleSuccessfulDecoding(IRrecv *aIRReceiverInstance) { } /* - * This handler is called in ISR context after IrReceiver.ReceiveInterruptHandler() if SUPPORT_MULTIPLE_RECEIVER_INSTANCES is active. + * If SUPPORT_MULTIPLE_RECEIVER_INSTANCES is active, this handler is called in ISR context after IrReceiver.ReceiveInterruptHandler(). * Here we just call the standard ReceiveInterruptHandler for the second receiver. * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving. */ diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 0c796c852..7b2715263 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -46,8 +46,6 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. - /* * Specify which protocol(s) should be used for decoding. * If no protocol is defined, all protocols (except Bang&Olufsen) are active. @@ -72,15 +70,19 @@ // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less +#define RAW_BUFFER_LENGTH 360 +# else // Here we most likely have 2 k RAM or more -#define RAW_BUFFER_LENGTH 700 // we require 2 buffer of this size for this example +#define RAW_BUFFER_LENGTH 750 # endif -# if !((defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)) +#endif + +#if RAMSIZE >= 0x1000 // Here we most likely have 4 k RAM or more -#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us -# endif +#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve timing values above 12750 us #endif //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. @@ -98,6 +100,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include int SEND_BUTTON_PIN = APPLICATION_PIN; diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino index 263b42eb2..9f79eac29 100644 --- a/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino +++ b/examples/ReceiveAndSendDistanceWidth/ReceiveAndSendDistanceWidth.ino @@ -46,21 +46,18 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. -#if !defined(IR_SEND_PIN) -#define IR_SEND_PIN 3 -#endif - /* * Specify DistanceWidthProtocol for decoding. This must be done before the #include */ #define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less #define RAW_BUFFER_LENGTH 360 -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) +# else +// Here we most likely have 2 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif #endif @@ -75,6 +72,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include #define SEND_BUTTON_PIN APPLICATION_PIN diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino index 5ffd427e4..7a598f25d 100644 --- a/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino +++ b/examples/ReceiveAndSendHob2Hood/ReceiveAndSendHob2Hood.ino @@ -40,7 +40,7 @@ //#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 "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include // IR commands from AEG hob2hood device diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index e13a782a3..bcfac1b82 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -34,7 +34,7 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. //#define LOCAL_DEBUG // If defined, print timing for each received data set (the same as if DEBUG_BUTTON_PIN was connected to low) @@ -86,8 +86,9 @@ // #if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it may require up to 750. Default is 200. -# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE >= 0x400 +// Here we have 1 k RAM or more #define RAW_BUFFER_LENGTH 750 # endif #endif diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveDump/ReceiveDump.ino b/examples/ReceiveDump/ReceiveDump.ino index 8415b4ad8..84b570061 100644 --- a/examples/ReceiveDump/ReceiveDump.ino +++ b/examples/ReceiveDump/ReceiveDump.ino @@ -33,12 +33,14 @@ */ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. - #if !defined(RAW_BUFFER_LENGTH) -// 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 730 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less +#define RAW_BUFFER_LENGTH 360 +# else +// Here we most likely have 2 k RAM or more +#define RAW_BUFFER_LENGTH 750 // this allows usage of 16 bit raw buffer, for RECORD_GAP_MICROS > 20000 # endif #endif @@ -54,10 +56,9 @@ */ //#define MARK_EXCESS_MICROS 40 // Adapt it to your IR receiver module. 40 is recommended for the cheap VS1838 modules at high intensity. //#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us - //#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols //#define DEBUG // Activate this for lots of lovely debug output from the decoders. - +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include //+============================================================================= diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino index 179c1be6d..f7277fa6b 100644 --- a/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino +++ b/examples/ReceiveOneAndSendMultiple/ReceiveOneAndSendMultiple.ino @@ -96,7 +96,7 @@ #define DECODE_SAMSUNG #define ADDRESS_OF_SAMSUNG_REMOTE 0x07 // The value you see as address in printIRResultShort() -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include void sendSamsungSmartHubMacro(bool aDoSelect); diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendAndReceive/SendAndReceive.ino b/examples/SendAndReceive/SendAndReceive.ino index 549541ab7..7aaabf8c5 100644 --- a/examples/SendAndReceive/SendAndReceive.ino +++ b/examples/SendAndReceive/SendAndReceive.ino @@ -48,7 +48,7 @@ //#define DEBUG // Activate this for lots of lovely debug output from the decoders. -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include #define DELAY_AFTER_SEND 2000 diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino index eb2fcdd02..d6b44faa3 100644 --- a/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino +++ b/examples/SendBoseWaveDemo/SendBoseWaveDemo.ino @@ -39,7 +39,7 @@ //#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include //...................................................................... diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendDemo/SendDemo.ino b/examples/SendDemo/SendDemo.ino index 32a22f689..d11622003 100644 --- a/examples/SendDemo/SendDemo.ino +++ b/examples/SendDemo/SendDemo.ino @@ -32,8 +32,6 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. - #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 @@ -45,6 +43,9 @@ //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition //#define USE_ACTIVE_HIGH_OUTPUT_FOR_NO_SEND_PWM // Simulate an active high receiver signal instead of an active low signal. //#define NO_LED_FEEDBACK_CODE // Saves 322 bytes program memory + +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. + #if FLASHEND <= 0x1FFF // For 8k flash or less like ATtiny85 #define NO_LED_FEEDBACK_CODE #endif @@ -175,7 +176,7 @@ void loop() { delay(DELAY_AFTER_SEND); if (sRepeats == 0) { -#if FLASHEND >= 0x3FFF && ((!defined(RAMEND) && !defined(RAMSIZE)) || (defined(RAMEND) && RAMEND > 0x6FF) || (defined(RAMSIZE) && RAMSIZE > 0x6FF)) +#if FLASHEND >= 0x3FFF && RAMSIZE >= 0x600 /* * For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. * Send constant values only once in this demo @@ -234,7 +235,8 @@ void loop() { 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 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, + NO_REPEATS); // Panasonic is a Kaseikyo variant # else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant # endif @@ -379,9 +381,9 @@ void loop() { IrSender.sendSony(sAddress & 0x1FFF, sCommand & 0x7F, sRepeats, SIRCS_20_PROTOCOL); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Samsung 8 bit command")); + Serial.println(F("Send Samsung 8 bit command and 8 bit address")); Serial.flush(); - IrSender.sendSamsung(sAddress, sCommand, sRepeats); + IrSender.sendSamsung(sAddress & 0xFF, sCommand, sRepeats); delay(DELAY_AFTER_SEND); Serial.println(F("Send Samsung 8 bit command and 16 bit address")); @@ -392,6 +394,7 @@ void loop() { Serial.println(F("Send Samsung 16 bit command and address")); Serial.flush(); IrSender.sendSamsung16BitAddressAndCommand(sAddress, s16BitCommand, sRepeats); + delay(DELAY_AFTER_SEND); Serial.println(F("Send Samsung48 16 bit command")); Serial.flush(); @@ -410,12 +413,12 @@ void loop() { Serial.println(F("Send Marantz variant of RC5x with 6 command bits and additional command extension")); Serial.flush(); - IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sCommandExtension, sRepeats); + IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x3F, sRepeats, sCommandExtension); delay(DELAY_AFTER_SEND); Serial.println(F("Send Marantz variant of RC5x with 7 command bits and additional command extension")); Serial.flush(); - IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sCommandExtension, sRepeats); + IrSender.sendRC5Marantz(sAddress & 0x1F, sCommand & 0x7F, sRepeats, sCommandExtension); delay(DELAY_AFTER_SEND); Serial.println(F("Send RC6")); @@ -428,7 +431,7 @@ void loop() { 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. +#if FLASHEND >= 0x3FFF && RAMSIZE >= 0x400 // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. Serial.println(F("Send MagiQuest")); Serial.flush(); diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index 7dc2ca86f..b32dcc95f 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -53,7 +53,7 @@ #define INFO // Deactivate this to save program memory and suppress info output from the LG-AC driver. //#define DEBUG // Activate this for more output from the LG-AC driver. -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendProntoDemo/SendProntoDemo.ino b/examples/SendProntoDemo/SendProntoDemo.ino index f08a7035b..963a22693 100644 --- a/examples/SendProntoDemo/SendProntoDemo.ino +++ b/examples/SendProntoDemo/SendProntoDemo.ino @@ -38,7 +38,7 @@ //#define NO_LED_FEEDBACK_CODE // Saves 266 bytes program memory -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include #define NUMBER_OF_REPEATS 3U diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SendRawDemo/SendRawDemo.ino b/examples/SendRawDemo/SendRawDemo.ino index 02f28f4ca..5a1e59915 100644 --- a/examples/SendRawDemo/SendRawDemo.ino +++ b/examples/SendRawDemo/SendRawDemo.ino @@ -45,7 +45,7 @@ //#define NO_LED_FEEDBACK_CODE // Saves 220 bytes program memory //#define USE_OPEN_DRAIN_OUTPUT_FOR_SEND_PIN // Use or simulate open drain output mode at send pin. Attention, active state of open drain is LOW, so connect the send LED between positive supply and send pin! -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include void setup() { diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index 84b040376..bff3d4749 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -65,10 +65,7 @@ //#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 - */ -#include "PinDefinitionsAndMore.h" +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include // include the library void setup() { diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino index 91819446b..27c0be7f9 100644 --- a/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino +++ b/examples/SimpleReceiverForHashCodes/SimpleReceiverForHashCodes.ino @@ -32,7 +32,7 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. /* * Specify which protocol(s) should be used for decoding. @@ -40,16 +40,17 @@ */ #define DECODE_HASH // special decoder for all protocols #if !defined(RAW_BUFFER_LENGTH) -# if !((defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF)) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE >= 0x400 +// Here we have 1 k RAM or more +#define RAW_BUFFER_LENGTH 750 +# elif RAMSIZE >= 0x800 +// Here we have 2 k RAM or more #define RAW_BUFFER_LENGTH 1000 // Especially useful for unknown and probably long protocols # endif #endif //#define DEBUG // Activate this for lots of lovely debug output from the decoders. -/* - * 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 void setup() { diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index 91797630e..7632ca3aa 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -5,7 +5,7 @@ * 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-2025 Armin Joachimsmeyer + * Copyright (C) 2020-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. @@ -21,10 +21,7 @@ //#define USE_NO_SEND_PWM // Use no carrier PWM, just simulate an active low receiver signal. Overrides SEND_PWM_BY_TIMER definition //#define NO_LED_FEEDBACK_CODE // Saves 216 bytes program memory -/* - * This include defines the actual pin number for pins like IR_RECEIVE_PIN, IR_SEND_PIN for many different boards and architectures - */ -#include "PinDefinitionsAndMore.h" +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include // include the library void setup() { diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 84f75b81a..65d1da19f 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -50,8 +50,6 @@ #include -#include "PinDefinitionsAndMore.h" // Set IR_RECEIVE_PIN for different CPU's - //#define DEBUG // to see if attachInterrupt is used //#define TRACE // to see the state of the ISR state machine @@ -67,6 +65,7 @@ */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received. +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include "TinyIRReceiver.hpp" // include the code void setup() { diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index d0753b645..a06f9c33b 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -46,7 +46,7 @@ */ #include -#include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include "TinyIRSender.hpp" diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index b3d71d11a..cee0c29fc 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -363,6 +363,9 @@ void noTone(uint8_t aPinNumber){ #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif -#if !defined (RAMEND) -#define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined +#if !defined (RAMSIZE) && defined(RAMEND) && defined(RAMSTART) +#define RAMSIZE (RAMEND - RAMSTART + 1) // +#endif +#if !defined (RAMSIZE) +#define RAMSIZE 0x1000 // 4k Dummy value for platforms where RAMSIZE is not defined #endif diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index 4431b09e4..d28d0fafa 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -33,17 +33,6 @@ #include -#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. - -#if !defined(RAW_BUFFER_LENGTH) -// For air condition remotes it requires 600 (maximum for 2k RAM) to 750. Default is 112 if DECODE_MAGIQUEST is enabled, otherwise 100. -# if (defined(RAMEND) && RAMEND <= 0x4FF) || (defined(RAMSIZE) && RAMSIZE < 0x4FF) -#define RAW_BUFFER_LENGTH 360 -# elif (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF) -#define RAW_BUFFER_LENGTH 400 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten. -# endif -#endif - //#define EXCLUDE_UNIVERSAL_PROTOCOLS // Saves up to 1000 bytes program memory. //#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 240 bytes program memory if IrSender.write is used //#define 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. @@ -58,6 +47,19 @@ //#define NO_LED_SEND_FEEDBACK_CODE // Saves 38 bytes program memory //#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. + +#if !defined(RAW_BUFFER_LENGTH) +// Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less +#define RAW_BUFFER_LENGTH 360 +# elif RAMSIZE <= 0x800 +// Here we have 2 k RAM or less, otherwise use default of 750 +#define RAW_BUFFER_LENGTH 400 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten. +# endif +#endif + //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, @@ -114,6 +116,8 @@ #define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints errors which prevents data to be decoded as distance width data #include +#include "TinyIRSender.hpp" + #if defined(APPLICATION_PIN) && !defined(DEBUG_BUTTON_PIN) #define DEBUG_BUTTON_PIN APPLICATION_PIN // if held low, print timing for each received data #else @@ -531,7 +535,7 @@ void loop() { delay(DELAY_AFTER_SEND); #endif // defined(DECODE_NEC) -#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 FLASHEND >= 0x7FFF && RAMSIZE >= 0x600 // For 32k flash or more, like Uno. Code does not fit in program memory of ATtiny1604 etc. if (sCommand == 0x76) { /* * Do this only once at the first loop @@ -605,7 +609,8 @@ void loop() { 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 - IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, NO_REPEATS); // Panasonic is a Kaseikyo variant + IrSender.sendPulseDistanceWidthFromPGMArray_P(&KaseikyoProtocolConstants, (IRDecodedRawDataType*) &tRawDataPGM[0], 48, + NO_REPEATS); // Panasonic is a Kaseikyo variant checkReceive(0x0B, 0x10); # else IrSender.sendPulseDistanceWidth_P(&KaseikyoProtocolConstants, 0xA010B02002, 48, NO_REPEATS); // Panasonic is a Kaseikyo variant @@ -798,6 +803,21 @@ void loop() { delay(DELAY_AFTER_SEND); # endif // defined(DECODE_MAGIQUEST) } // end of once at first loop + + Serial.println(F("Send NEC with TinyIRSender")); + Serial.flush(); + sendNEC(IR_SEND_PIN, (uint8_t) sAddress, sCommand, sRepeats); // Casting saves 18 bytes + checkReceive(sAddress & 0xFF, sCommand); + delay(DELAY_AFTER_SEND); + +# if defined(DECODE_FAST) + Serial.println(F("Send FAST with TinyIRSender")); + Serial.flush(); + sendFAST(IR_SEND_PIN, sCommand, sRepeats); + checkReceive(0, sCommand); + delay(DELAY_AFTER_SEND); +# endif + #endif // if FLASHEND >= 0x7FFF #if defined(DECODE_NEC) diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index f5246ce9e..9b089d256 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -369,6 +369,38 @@ rawIRTimings[112]: Duration=64900us +Send NEC with TinyIRSender +Protocol=NEC Address=0xF1, Command=0x76, Raw-Data=0x89760EF1, 32 bits, LSB first, Gap=790250us, Duration=75050us +Send with: IrSender.sendNEC(0xF1, 0x76, ); +rawIRTimings[68]: + -790250 + +8900,-5250 + + 600,-1950 + 600,- 650 + 600,- 600 + 600,- 650 + + 500,-2000 + 650,-1900 + 600,-1950 + 600,-1950 + + 650,- 600 + 550,-1950 + 650,-1900 + 650,-1900 + + 650,- 600 + 650,- 550 + 600,- 650 + 600,- 600 + + 650,- 550 + 650,-1900 + 600,-1950 + 600,- 650 + + 600,-1950 + 650,-1900 + 650,-1900 + 550,- 650 + + 600,-1950 + 650,- 550 + 650,- 600 + 600,-1900 + + 650,- 600 + 600,- 600 + 600,- 650 + 600,-1950 + + 600 +Duration=75050us + + +Send FAST with TinyIRSender +Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=764700us, Duration=32050us +Send with: IrSender.sendFAST(0x76, ); +rawIRTimings[36]: + -764700 + +2100,-1200 + + 550,- 600 + 550,-1850 + 600,-1750 + 600,- 550 + + 500,-1900 + 600,-1800 + 550,-1800 + 550,- 600 + + 600,-1800 + 550,- 600 + 600,- 550 + 550,-1800 + + 600,- 550 + 550,- 600 + 600,- 550 + 550,-1800 + + 550 +Duration=32050us + + Send Onkyo (NEC with 16 bit command) Protocol=Onkyo Address=0xFFF1, Command=0x7776, Raw-Data=0x7776FFF1, 32 bits, LSB first, Gap=791150us, Duration=76750us Send with: IrSender.sendOnkyo(0xFFF1, 0x7776, ); @@ -823,7 +855,7 @@ Duration=27150us Send FAST Protocol=FAST Address=0x0, Command=0x76, Raw-Data=0x8976, 16 bits, LSB first, Gap=746700us, Duration=29250us -Send with: IrSender.sendFAST(0x0, 0x76, ); +Send with: IrSender.sendFAST(0x76, ); rawIRTimings[36]: -746700 +2200,-1000 @@ -965,7 +997,38 @@ rawIRTimings[68]: + 600,- 550 + 600,- 500 + 600,- 550 + 600,-1650 + 600,-1650 + 650,-1550 + 600,-1650 + 650,- 500 + 600 -Duration=67900us + + +Send NEC with TinyIRSender +Protocol=NEC Address=0xF2, Command=0x87, Raw-Data=0x78870DF2, 32 bits, LSB first, Gap=744800us, Duration=75100us +Send with: IrSender.sendNEC(0xF2, 0x87, ); +rawIRTimings[68]: + -744800 + +8950,-5250 + + 550,- 650 + 650,-1900 + 650,- 550 + 550,- 700 + + 650,-1900 + 650,-1900 + 600,-1950 + 600,-1950 + + 650,-1900 + 600,- 600 + 550,-2000 + 650,-1900 + + 600,- 600 + 650,- 600 + 600,- 600 + 650,- 600 + + 600,-1950 + 600,-1950 + 650,-1900 + 600,- 600 + + 550,- 700 + 650,- 550 + 650,- 600 + 600,-1950 + + 650,- 550 + 650,- 550 + 650,- 600 + 600,-1950 + + 600,-1950 + 600,-1950 + 600,-1950 + 600,- 600 + + 600 +Duration=75100us + + +Send FAST with TinyIRSender +Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=745000us, Duration=32150us +Send with: IrSender.sendFAST(0x87, ); +rawIRTimings[36]: + -745000 + +2050,-1250 + + 600,-1800 + 600,-1800 + 550,-1800 + 600,- 550 + + 500,- 650 + 550,- 600 + 550,- 600 + 600,-1800 + + 550,- 600 + 550,- 600 + 550,- 550 + 550,-1850 + + 600,-1800 + 600,-1750 + 600,-1800 + 550,- 600 + + 600 +Duration=32150usDuration=67900us Send Onkyo (NEC with 16 bit command) @@ -1433,7 +1496,7 @@ Duration=27150us Send FAST Protocol=FAST Address=0x0, Command=0x87, Raw-Data=0x7887, 16 bits, LSB first, Gap=726950us, Duration=29200us -Send with: IrSender.sendFAST(0x0, 0x87, ); +Send with: IrSender.sendFAST(0x87, ); rawIRTimings[36]: -726950 +2200,-1000 diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index b8ae36ed1..1732cff14 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -1968,6 +1968,8 @@ void IRrecv::printIRSendUsage(Print *aSerial) { * PulseDistanceWidthFromArray(38, 8900, 4350, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, , ); * or * (0x
, 0x, ); + * or + * FAST(0x, ); */ if (decodedIRData.protocol == UNKNOWN){ aSerial->print(F("Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, ")); @@ -2020,20 +2022,28 @@ void IRrecv::printIRSendUsage(Print *aSerial) { if (decodedIRData.protocol == MAGIQUEST) { # if (__INT_WIDTH__ < 32) aSerial->print(decodedIRData.decodedRawData, HEX); + aSerial->print(F(", 0x")); # else PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX); + aSerial->print(F(", 0x")); # endif } else { +# if defined(DECODE_FAST) + // do not print address parameter for FAST protocol + if (decodedIRData.protocol != FAST) { + aSerial->print(decodedIRData.address, HEX); + aSerial->print(F(", 0x")); + } +# else aSerial->print(decodedIRData.address, HEX); + aSerial->print(F(", 0x")); +# endif } #else - /* - * New decoders have address and command - */ aSerial->print(decodedIRData.address, HEX); + aSerial->print(F(", 0x")); #endif - aSerial->print(F(", 0x")); aSerial->print(decodedIRData.command, HEX); if (decodedIRData.protocol == SONY) { printNumberOfRepeats(aSerial); diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 210ed20fc..3d8369859 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -167,10 +167,11 @@ #else # if defined(SEND_PWM_BY_TIMER) # if defined(IR_SEND_PIN) +#pragma message("INFO: Since SEND_PWM_BY_TIMER is defined, the current value of IR_SEND_PIN \"" STR(IR_SEND_PIN) "\" is discarded and will be replaced in IRTimer.hpp by the value determined by the timer used for PWM generation." ) +//#warning INFO: Since SEND_PWM_BY_TIMER is defined, the current value of IR_SEND_PIN is discarded and will be replaced in IRTimer.hpp by the value determined by the timer used for PWM generation #undef IR_SEND_PIN // to avoid warning 3 lines later -#warning Since SEND_PWM_BY_TIMER is defined, the existing value of IR_SEND_PIN is discarded and replaced by the value determined by timer used for PWM generation # endif -#define IR_SEND_PIN DeterminedByTimer // must be set here, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp +//#define IR_SEND_PIN DeterminedByTimer // Must be set here to a dummy value, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp # endif #endif @@ -212,9 +213,9 @@ #define IR_SEND_DUTY_CYCLE_PERCENT 30 // 30 saves power and is compatible to the old existing code #endif -#define MILLIS_IN_ONE_SECOND 1000L +#define MILLIS_IN_ONE_SECOND 1000U // unused #define MICROS_IN_ONE_SECOND 1000000L -#define MICROS_IN_ONE_MILLI 1000L +#define MICROS_IN_ONE_MILLI 1000U #if defined(NO_LED_FEEDBACK_CODE) // convert to receive and send macros @@ -229,7 +230,6 @@ #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. @@ -241,6 +241,8 @@ #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE) #include "private/IRTimer.hpp" // defines IR_SEND_PIN for AVR and SEND_PWM_BY_TIMER +#include "IRremoteInt.h" + # 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) diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 02f904acf..6f99f6c76 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -65,17 +65,18 @@ * 16 bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) requires a buffer length of 36. * MAGIQUEST requires a buffer length of 112. * Air conditioners often send a longer protocol data stream up to 750 bits. + * Default is 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM */ #if !defined(RAW_BUFFER_LENGTH) -# if (defined(RAMEND) && RAMEND <= 0x2FF) || (defined(RAMSIZE) && RAMSIZE < 0x2FF) -// for RAMsize <= 512 bytes +# if (defined(RAMSIZE) && RAMSIZE <= 0x200) || (defined(RAMEND) && RAMEND <= 0x2FF) // assuming RAMSTART at 0x100 +// 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 +# elif (defined(RAMSIZE) && RAMSIZE < 0x8FF) || (defined(RAMEND) && RAMEND <= 0x8FF) // assuming RAMSTART at 0x100 +// 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 // For undefined or bigger RAMsize -#define RAW_BUFFER_LENGTH 750 // The value for air condition remotes. +#define RAW_BUFFER_LENGTH 750 // The value required for air condition remotes. # endif #endif #if RAW_BUFFER_LENGTH % 2 == 1 diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 6f498b532..35fa0e583 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -66,7 +66,7 @@ #endif /* - * Generate 38 kHz IR signal by bit banging + * Generate 38 kHz IR signal by bit banging and using delayMicroseconds() and micros() */ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { unsigned long tStartMicros = micros(); @@ -86,7 +86,7 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { * PWM pause timing and end check * Minimal pause duration is 4.3 us */ - tNextPeriodEnding += 26; // for 38 kHz + tNextPeriodEnding += 26; // 26.3 us period for 38 kHz; 26 us -> 38.48 kHz do { tMicros = micros(); // we have only 4 us resolution for AVR @16MHz /* @@ -98,7 +98,7 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { if (tDeltaMicros >= aMarkMicros - (112 / (F_CPU / MICROS_IN_ONE_SECOND))) { // To compensate for call duration - 112 is an empirical value #else if (tDeltaMicros >= aMarkMicros) { - #endif +#endif return; } } while (tMicros < tNextPeriodEnding); diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index faeaa5afd..7087d75e4 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -311,15 +311,14 @@ int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Paramete #define __digitalPinToPortReg(P) (((P) <= 7) ? &PORTA : &PORTB) #define __digitalPinToDDRReg(P) (((P) <= 7) ? &DDRA : &DDRB) #define __digitalPinToPINReg(P) (((P) <= 7) ? &PINA : &PINB) -# endif -# if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) +# if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) // https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/variants/tinyx41_cw/pins_arduino.h#L334 // Clockwise layout #define __digitalPinToBit(P) (((P) <= 7) ? (P) : ((P) == 11 ? (3) : 10 - (P))) -# else +# else #define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 ) +# endif # endif - #endif #if !defined(digitalWriteFast) diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index ca64000db..a86eef1b7 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -77,7 +77,7 @@ //#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) +# if (defined(RAMSIZE) && RAMSIZE <= 0x800) || (defined(RAMEND) && RAMEND <= 0x8FF) #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 50 // To save program space, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds # else #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds diff --git a/src/ir_FAST.hpp b/src/ir_FAST.hpp index 89cef8f4b..65017ed97 100644 --- a/src/ir_FAST.hpp +++ b/src/ir_FAST.hpp @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2023 Armin Joachimsmeyer + * Copyright (c) 2023-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 79c8809e3..54aff4880 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -183,7 +183,7 @@ void IRsend::sendNEC(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOf /** * There is NO delay after the last sent repeat! - * @param aNumberOfRepeats If < 0 then only a special repeat frame without leading and trailing space + * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */ void IRsend::sendOnkyo(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { diff --git a/src/ir_OpenLASIR.hpp b/src/ir_OpenLASIR.hpp index bceecc0a1..945452248 100644 --- a/src/ir_OpenLASIR.hpp +++ b/src/ir_OpenLASIR.hpp @@ -61,11 +61,11 @@ * OpenLASIR uses the same timing as NEC but rearranges the address/command structure: * - 8-bit address with 8-bit inverted complement (for error checking) * - 16-bit command with no error check - * Bits 0-7: Block ID (8 bits) ↠Address low byte - * Bits 8-15: ~Block ID (8 bits) ↠Address high byte (inverted, for error check) - * Bits 16-23: Device ID (8 bits) ↠Command bits 0-7 - * Bits 24-28: Mode (5 bits) ↠Command bits 8-12 - * Bits 29-31: Data (color, etc.) (3 bits) ↠Command bits 13-15 + * Bits 0-7: Block ID (8 bits) - Address low byte + * Bits 8-15: ~Block ID (8 bits) - Address high byte (inverted, for error check) + * Bits 16-23: Device ID (8 bits) - Command bits 0-7 + * Bits 24-28: Mode (5 bits) - Command bits 8-12 + * Bits 29-31: Data (color, etc.) (3 bits) - Command bits 13-15 * * This is the opposite of NEC Extended, which uses 16-bit address and 8-bit validated command. * @@ -182,7 +182,7 @@ uint16_t IRsend::computeOpenLASIRRawCommand(uint8_t aDeviceID, uint8_t aMode, ui * * @param aAddress 8-bit address (Block ID). Only lower 8 bits are used. * @param aCommand 16-bit command (Device ID + Mode + Data). - * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent. */ void IRsend::sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth_P(&NECProtocolConstants, computeOpenLASIRRawDataAndChecksum(aAddress, aCommand), OPENLASIR_BITS, @@ -197,7 +197,7 @@ void IRsend::sendOpenLASIR(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNum * @param aDeviceID 8-bit Device ID. * @param aMode 5-bit Mode. * @param aData 3-bit Data (color, etc.). - * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent. */ void IRsend::sendOpenLASIR(uint8_t aAddress, uint8_t aDeviceID, uint8_t aMode, uint8_t aData, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth_P(&NECProtocolConstants, @@ -208,7 +208,7 @@ void IRsend::sendOpenLASIR(uint8_t aAddress, uint8_t aDeviceID, uint8_t aMode, u /** * Send raw 32-bit OpenLASIR data. * @param aRawData The pre-computed 32-bit raw data. - * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent. + * @param aNumberOfRepeats If < 0 then only a special NEC repeat frame will be sent. */ void IRsend::sendOpenLASIRRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth_P(&NECProtocolConstants, aRawData, OPENLASIR_BITS, aNumberOfRepeats); diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 68fd08ac5..5c5c7a23d 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -86,7 +86,7 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only // // MARANTZ // https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended -// Marantz uses RC5X and adds a a pause after the address / first 8 bits +// Marantz uses RC5X and adds a 3.5 ms pause after the address / first 8 bits // After the 6 bit command (of RC5) an additional 6 bit command extension is sent -> 20 bits incl. field bit and start bit // #define RC5_ADDRESS_BITS 5 @@ -127,7 +127,6 @@ void IRsend::setToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue) { } /** - * !!! Not tested, because no Marantz remote was at hand and no receive function was contributed!!! * Send function for the Marantz version of RC5(X) with a pause of 4 * RC5_UNIT after address / first 8 bits * and before the bits of command and command extension. * Marantz seems to require at least one repetition with toggle bit set @@ -176,14 +175,14 @@ void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNum // start bit is sent by sendBiphaseData followed by the field bit and toggle bit and address sendBiphaseData(RC5_UNIT, tIRData, RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS); // pause before the bits of command and command extension to indicate that it's Marantz-RC5x - space(MARANTZ_PAUSE_DURATION); // Marantz-RC5x has a pause before the bits of command and command extension + space(MARANTZ_PAUSE_DURATION); // 3556, Marantz-RC5x has a pause before the bits of command and command extension // send command and command extension sendBiphaseData(RC5_UNIT, tIRExtData, RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS, false); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { - // send repeated command in a fixed raster + // send repeated command in a fixed raster of 100 ms delay(MARANTZ_REPEAT_DISTANCE / MICROS_IN_ONE_MILLI); } } diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 6b23bc724..462ca4846 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -197,7 +197,7 @@ void IRsend::sendSamsung(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumb /** * Maybe no one needs it in the wild... - * As above, but we are able to send e.g. 0x0042 as 16 bit address + * As above, but we are able to send e.g. 0x0042 as 16 bit address, which is otherwise interpreted as 8 bit address * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent */ void IRsend::sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats) { @@ -214,7 +214,7 @@ void IRsend::sendSamsung16BitAddressAnd8BitCommand(uint16_t aAddress, uint8_t aC /** * Maybe no one needs it in the wild... - * As above, but we are able to send e.g. 0x0042 as 16 bit address + * As above, but we are able to send e.g. 0x0042 as 16 bit address, which is otherwise interpreted as 8 bit address * @param aNumberOfRepeats If < 0 then only a special repeat frame will be sent */ void IRsend::sendSamsung16BitAddressAndCommand(uint16_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index b549ffe11..c6ca6dc87 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -11,7 +11,7 @@ ************************************************************************************* * MIT License * - * Copyright (c) 2021-2025 Armin Joachimsmeyer + * Copyright (c) 2021-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,6 +32,14 @@ * ************************************************************************************ */ + +/** + * Hardware PWM generation of sending signal with 8 bit timer: + * 16 MHZ F_CPU and 38 kHz -> prescaling = 2, divider = 210.526 -> 38.1 kHz with divider 210 + * 8 MHZ F_CPU and 38 kHz -> no prescaling , divider = 210.526 -> 38.1 kHz with divider 210 + * 4 MHZ F_CPU and 38 kHz -> no prescaling , divider = 105.26 -> 38.1 kHz with divider 105 + * 1 MHZ F_CPU and 38 kHz -> no prescaling , divider = 26.31 -> 38.4 kHz with divider 36 + */ #ifndef _IR_TIMER_HPP #define _IR_TIMER_HPP @@ -1049,7 +1057,7 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible GTCCR = _BV(PWM1B) | _BV(COM1B0);// PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match # else - const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz); // 210 for 16 MHz and 38 kHz + const uint16_t tPWMWrapValue = ((F_CPU / 2) / 1000) / (aFrequencyKHz); // 210.526 for 16 MHz and 38 kHz or 38.1 kHz for 210 TCCR1 = _BV(CTC1) | _BV(CS11); // CTC1 = 1: TOP value set to OCR1C, CS11 Prescaling by 2 OCR1C = tPWMWrapValue - 1; OCR1B = ((tPWMWrapValue * IR_SEND_DUTY_CYCLE_PERCENT_FOR_LEVEL_HIGH) / 100) - 1; @@ -2343,9 +2351,12 @@ void timerConfigForSend(uint16_t aFrequencyKHz) { (void) aFrequencyKHz; } # endif // defined(SEND_PWM_BY_TIMER) - #endif // defined(DOXYGEN / CPU_TYPES) +#if defined(SEND_PWM_BY_TIMER) && defined(IR_SEND_PIN) +#pragma message("INFO: Value of IR_SEND_PIN determined by SEND_PWM_BY_TIMER is: " STR(IR_SEND_PIN)) +#endif + /** @}*/ /** @}*/ #endif // _IR_TIMER_HPP From 95dbe9ae48cd3936f7829329b7135b2de543024e Mon Sep 17 00:00:00 2001 From: ArminJo Date: Mon, 16 Mar 2026 18:06:38 +0100 Subject: [PATCH 124/133] Improved software PWM generation --- .github/workflows/LibraryBuild.yml | 36 ++++++++++++----- .../AllProtocolsOnLCD/PinDefinitionsAndMore.h | 6 +-- examples/CallbackDemo/PinDefinitionsAndMore.h | 6 +-- examples/ControlRelay/PinDefinitionsAndMore.h | 6 +-- .../IRDispatcherDemo/PinDefinitionsAndMore.h | 6 +-- .../IRremoteExtensionClass.cpp | 2 + .../PinDefinitionsAndMore.h | 6 +-- examples/MicroGirs/PinDefinitionsAndMore.h | 6 +-- .../MultipleReceivers/PinDefinitionsAndMore.h | 6 +-- .../ReceiveAndSend/PinDefinitionsAndMore.h | 6 +-- .../PinDefinitionsAndMore.h | 6 +-- .../PinDefinitionsAndMore.h | 6 +-- examples/ReceiveDemo/PinDefinitionsAndMore.h | 6 +-- examples/ReceiveDump/PinDefinitionsAndMore.h | 6 +-- .../PinDefinitionsAndMore.h | 6 +-- .../SendAndReceive/PinDefinitionsAndMore.h | 6 +-- .../SendBoseWaveDemo/PinDefinitionsAndMore.h | 6 +-- examples/SendDemo/PinDefinitionsAndMore.h | 6 +-- .../PinDefinitionsAndMore.h | 6 +-- .../SendProntoDemo/PinDefinitionsAndMore.h | 6 +-- examples/SendRawDemo/PinDefinitionsAndMore.h | 6 +-- .../SimpleReceiver/PinDefinitionsAndMore.h | 6 +-- .../PinDefinitionsAndMore.h | 6 +-- examples/SimpleSender/PinDefinitionsAndMore.h | 6 +-- examples/TinyReceiver/PinDefinitionsAndMore.h | 6 +-- examples/TinySender/PinDefinitionsAndMore.h | 6 +-- examples/UnitTest/PinDefinitionsAndMore.h | 6 +-- library.properties | 2 +- src/IRSend.hpp | 40 +++++++++---------- src/IRremote.hpp | 14 +++---- src/TinyIRSender.hpp | 18 ++++----- src/private/IRTimer.hpp | 2 + 32 files changed, 90 insertions(+), 174 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 84ce6eb73..854aa2089 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -80,7 +80,7 @@ jobs: - stm32duino:STM32F1:genericSTM32F103C - sandeepmistry:nRF5:BBCmicrobit - Seeeduino:samd:seeed_XIAO_m0:usbstack=arduino,debug=off,sercom4=include - - vega:riscv:aries_v3 +# - vega:riscv:aries_v3 # Specify parameters for each board. # With sketches-exclude you may exclude specific examples for a board. Use a comma separated list. @@ -143,6 +143,7 @@ jobs: - arduino-boards-fqbn: arduino:avr:leonardo build-properties: # the flags were put in compiler.cpp.extra_flags + SimpleSender: -DSEND_PWM_BY_TIMER TinyReceiver: -DNO_LED_FEEDBACK_CODE TinySender: -DNO_LED_FEEDBACK_CODE sketches-exclude: UnitTest # Sketch uses 28764 bytes (100%) of program storage space. Maximum is 28672 bytes @@ -155,23 +156,30 @@ jobs: TinySender: -DUSE_ONKYO_PROTOCOL -DENABLE_NEC2_REPEATS -DNO_LED_FEEDBACK_CODE - arduino-boards-fqbn: arduino:samd:arduino_zero_native +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware is not yet implemented for SAMD sketches-exclude: TinyReceiver,IRDispatcherDemo - arduino-boards-fqbn: arduino:renesas_uno:unor4wifi +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware not yet implemented for Arduino Uno R4 sketches-exclude: TinyReceiver,IRDispatcherDemo - 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 +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware is not yet implemented for SAMD sketches-exclude: TinyReceiver,IRDispatcherDemo - arduino-boards-fqbn: adafruit:samd:adafruit_itsybitsy_m4 platform-url: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware is not yet implemented for SAMD sketches-exclude: TinyReceiver,IRDispatcherDemo - - arduino-boards-fqbn: arduino:mbed:nano33ble - build-properties: # the flags were put in compiler.cpp.extra_flags - SimpleSender: -DSEND_PWM_BY_TIMER +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default # # RP2040 @@ -283,18 +291,20 @@ jobs: platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json sketches-exclude: TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware not implemented for STM32 All: -DRAW_BUFFER_LENGTH=750 - arduino-boards-fqbn: STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072 # ST version platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json sketches-exclude: TinyReceiver,IRDispatcherDemo - build-properties: # the flags were put in compiler.cpp.extra_flags - All: -DRAW_BUFFER_LENGTH=750 +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware not implemented for STM32 - arduino-boards-fqbn: stm32duino:STM32F1:genericSTM32F103C # Roger Clark version platform-url: http://dan.drown.org/stm32duino/package_STM32duino_index.json sketches-exclude: TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER # PWM generation by hardware not implemented for STM32 All: -DRAW_BUFFER_LENGTH=750 # @@ -304,6 +314,7 @@ jobs: arduino-platform: arduino:avr,SparkFun:avr platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json # Arduino URL is not required here build-properties: # the flags were put in compiler.cpp.extra_flags. SEND_PWM_BY_TIMER is always enabled! + SimpleSender: -DSEND_PWM_BY_TIMER All: -DRAW_BUFFER_LENGTH=750 sketches-exclude: UnitTest # Sketch uses 28762 bytes (100%) of program storage space. Maximum is 28672 bytes. @@ -311,19 +322,22 @@ jobs: platform-url: https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json sketches-exclude: IRDispatcherDemo,MicroGirs,TinyReceiver build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware not implemented for NRF5 All: -DRAW_BUFFER_LENGTH=750 - 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,ReceiveDemo,SimpleReceiverForHashCodes # No print(uint64_t,.) available build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER #error PWM generation by hardware is not yet implemented for SAMD All: -DRAW_BUFFER_LENGTH=750 - - arduino-boards-fqbn: vega:riscv:aries_v3 - platform-url: https://gitlab.com/riscv-vega/vega-arduino/-/raw/main/package_vega_index.json - sketches-exclude: MicroGirs,SendLGAirConditionerDemo # No Stream:: available and readBytesUntil - build-properties: # the flags were put in compiler.cpp.extra_flags - All: -DF_CPU=100000000LL -DVEGA_ARIES_V3 -DRAW_BUFFER_LENGTH=750 -DCHANGE=1 +# - arduino-boards-fqbn: vega:riscv:aries_v3 +# platform-url: https://gitlab.com/riscv-vega/vega-arduino/-/raw/main/package_vega_index.json +# sketches-exclude: MicroGirs,SendLGAirConditionerDemo # No Stream:: available and readBytesUntil +# build-properties: # the flags were put in compiler.cpp.extra_flags +# SimpleSender: -DSEND_PWM_BY_TIMER +# All: -DF_CPU=100000000LL -DVEGA_ARIES_V3 -DRAW_BUFFER_LENGTH=750 -DCHANGE=1 # fail-fast: false # false -> do not cancel all jobs / architectures if one job fails diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/CallbackDemo/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/CallbackDemo/PinDefinitionsAndMore.h +++ b/examples/CallbackDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp index 587263de9..a110d8fb5 100644 --- a/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp +++ b/examples/IRremoteExtensionTest/IRremoteExtensionClass.cpp @@ -31,6 +31,8 @@ */ #include +#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. + /* * !!! The value of RAW_BUFFER_LENGTH (and some other macros) must be the same in all compile units !!! * Otherwise you may get warnings like "type 'struct IRData' itself violates the C++ One Definition Rule" diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index cee0c29fc..3dcce3ea8 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -351,12 +351,8 @@ void noTone(uint8_t aPinNumber){ #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) -#if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) -#define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation -#else -# if defined(SEND_PWM_BY_TIMER) +#if !(defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED)) && defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp -# endif #endif #if !defined (FLASHEND) diff --git a/library.properties b/library.properties index cb8f0aec6..1ada6ea35 100644 --- a/library.properties +++ b/library.properties @@ -6,5 +6,5 @@ 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, 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,riscv +architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,mbed,mbed_nano,rp2040,mbed_rp2040,renesas_uno,riscv,nRF5 includes=IRremote.hpp diff --git a/src/IRSend.hpp b/src/IRSend.hpp index d702c2390..22cb84ef2 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -667,8 +667,8 @@ void IRsend::sendPulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aPr aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aData, aNumberOfBits, aProtocolConstants->Flags); } -void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, IRDecodedRawDataType aData, - uint_fast8_t aNumberOfBits) { +void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, + IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits) { PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants; memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM, @@ -691,9 +691,9 @@ void IRsend::sendPulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants co * @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, IRDecodedRawDataType aData, - uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats, - void (*aSpecialSendRepeatFunction)()) { + uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, + IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, + int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)()) { if (aNumberOfRepeats < 0) { if (aSpecialSendRepeatFunction != nullptr) { @@ -1283,12 +1283,13 @@ void IRsend::mark(uint16_t aMarkMicros) { #else // defined(SEND_PWM_BY_TIMER) - unsigned long tMicrosOfEndOfNextPWMPause = micros(); + unsigned long tMicros = micros(); + unsigned long tMicrosOfEndOfNextPWMPause = tMicros; # if defined(LED_SEND_FEEDBACK_CODE) - unsigned long tStartMicros = tMicrosOfEndOfNextPWMPause + (136 / CLOCKS_PER_MICRO); // To compensate for call duration and activating of LED + unsigned long tEndMicros = tMicros + (136 / CLOCKS_PER_MICRO) + aMarkMicros; // 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 + unsigned long tEndMicros = tMicros + (112 / CLOCKS_PER_MICRO) + aMarkMicros; // To compensate for call duration - 112 is an empirical value #endif /*************************************************************************************************** @@ -1367,12 +1368,12 @@ void IRsend::mark(uint16_t aMarkMicros) { * 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 + * For an 8 MHz Attiny we measure 10 us, 18 us and 27 us pause. Minimal pause duration is 10 us. (80 us for 1MHz -> 12 kHz) *******************************************************************************************************************************/ - 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; + tMicrosOfEndOfNextPWMPause += periodTimeMicros; // Period time is 26 us for 38.46 kHz, 27 us for 37.04 kHz, 25 us for 40 kHz. +//#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 do { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles @@ -1391,18 +1392,17 @@ void IRsend::mark(uint16_t aMarkMicros) { * Check for end of mark duration / PWM generation ************************************************/ tMicros = micros(); - uint16_t tDeltaMicros = tMicros - tStartMicros; - // 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 (tDeltaMicros >= aMarkMicros) { + if (tMicros >= tEndMicros) { + // reset feedback led in the last pause before end #if defined(LED_SEND_FEEDBACK_CODE) setFeedbackLED(false); #endif -#if defined(__AVR__) - interrupts(); -#endif +//#if defined(__AVR__) +// interrupts(); // enable interrupts again before leaving mark() +//#endif return; } + } while (tMicros < tMicrosOfEndOfNextPWMPause); // = End of one PWM period } while (true); # endif diff --git a/src/IRremote.hpp b/src/IRremote.hpp index 3d8369859..409c7ea8e 100644 --- a/src/IRremote.hpp +++ b/src/IRremote.hpp @@ -160,18 +160,18 @@ */ //#define SEND_PWM_BY_TIMER // restricts send pin on many platforms to fixed pin numbers #if (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) -# if !defined(SEND_PWM_BY_TIMER) -#define SEND_PWM_BY_TIMER // the best and default method for ESP32 etc. -#warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default, since we have the resources and timing is more exact than the software generated one. If this is not intended, deactivate the line in IRremote.hpp over this warning message in file IRremote.hpp. +# if defined(SEND_PWM_BY_TIMER) +#pragma message("INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default, since we have the resources and timing is more exact than the software generated one.") +# else +#define SEND_PWM_BY_TIMER // the best and default method for ESP32 etc. If you want to use software generated PWM, you must deactivate this line. # endif #else # if defined(SEND_PWM_BY_TIMER) # if defined(IR_SEND_PIN) #pragma message("INFO: Since SEND_PWM_BY_TIMER is defined, the current value of IR_SEND_PIN \"" STR(IR_SEND_PIN) "\" is discarded and will be replaced in IRTimer.hpp by the value determined by the timer used for PWM generation." ) //#warning INFO: Since SEND_PWM_BY_TIMER is defined, the current value of IR_SEND_PIN is discarded and will be replaced in IRTimer.hpp by the value determined by the timer used for PWM generation -#undef IR_SEND_PIN // to avoid warning 3 lines later # endif -//#define IR_SEND_PIN DeterminedByTimer // Must be set here to a dummy value, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp +#define IR_SEND_PIN ToBeOverwrittenLaterByPinNumberDeterminedByTimer // Must be set here to a dummy value, since it is evaluated at IRremoteInt.h, before the include of private/IRTimer.hpp # endif #endif @@ -238,11 +238,11 @@ #include "digitalWriteFast.h" #endif +#include "IRremoteInt.h" // definition (or no definition) of IR_SEND_PIN define determines the IRSender function signatures + #if !defined(USE_IRREMOTE_HPP_AS_PLAIN_INCLUDE) #include "private/IRTimer.hpp" // defines IR_SEND_PIN for AVR and SEND_PWM_BY_TIMER -#include "IRremoteInt.h" - # 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) diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 35fa0e583..1ed865f20 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -69,9 +69,13 @@ * Generate 38 kHz IR signal by bit banging and using delayMicroseconds() and micros() */ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { - unsigned long tStartMicros = micros(); - unsigned long tNextPeriodEnding = tStartMicros; - unsigned long tMicros; + unsigned long tMicros = micros(); + unsigned long tNextPeriodEnding = tMicros; +#if defined(F_CPU) + unsigned long tEndMicros = tMicros + (112 / (F_CPU / MICROS_IN_ONE_SECOND)) + aMarkMicros; // To compensate for call duration - 112 is an empirical value +#else + unsigned long tEndMicros = tMicros + aMarkMicros; +#endif do { /* * Generate pulse @@ -92,13 +96,7 @@ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { /* * Exit the forever loop if aMarkMicros has reached */ - unsigned int tDeltaMicros = tMicros - tStartMicros; -#if defined(__AVR__) - // Just getting variables and check for end condition takes minimal 3.8 us - if (tDeltaMicros >= aMarkMicros - (112 / (F_CPU / MICROS_IN_ONE_SECOND))) { // To compensate for call duration - 112 is an empirical value -#else - if (tDeltaMicros >= aMarkMicros) { -#endif + if (tMicros >= tEndMicros) { return; } } while (tMicros < tNextPeriodEnding); diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index c6ca6dc87..4358904be 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -62,6 +62,8 @@ void timerConfigForSend(uint16_t aFrequencyKHz); // Initialization of timer hard void enableSendPWMByTimer(); // Switch on PWM generation void disableSendPWMByTimer(); // Switch off PWM generation +void IRReceiveTimerInterruptHandler(); // defined in IRReceive.hpp + // SEND_PWM_BY_TIMER for different architectures is enabled / defined at IRremote.hpp line 195. #if defined(SEND_PWM_BY_TIMER) && ( (defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE)) || defined(ARDUINO_ARCH_MBED) ) #define SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER // Receive timer and send generation timer are independent here. From c39a37e178f8829816b2b6fe0dc84e8ce04dd382 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Tue, 17 Mar 2026 09:02:07 +0100 Subject: [PATCH 125/133] Bumped TinyIR version to 2.3.0 - Renamed TinyReceiver*() functions to TinyIRReceiver*() --- README.md | 19 +++++++------ examples/TinyReceiver/TinyReceiver.ino | 6 ++-- src/IRCommandDispatcher.hpp | 6 ++-- src/IRremoteInt.h | 2 ++ src/TinyIR.h | 22 +++++++++++---- src/TinyIRReceiver.hpp | 39 ++++++++++++++++++++------ 6 files changed, 65 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 68661c518..75a4676eb 100644 --- a/README.md +++ b/README.md @@ -684,7 +684,7 @@ For applications only requiring NEC, NEC variants or FAST -see below- protocol, which has very **small code size of 500 bytes and does NOT require any timer**. ## Principle of operation -Unlike IRremote, which samples the input every 50 µs, the TinyReceiver receiver uses a **pin change interrupt** for on-the-fly decoding. +Unlike IRremote, which samples the input every 50 µs, the TinyIRReceiver uses a **pin change interrupt** for on-the-fly decoding. This restricts the range of protocols that can be recognised.
On each level change, the level and the time since the last change are used to incrementally decode the protocol.
With this operating principle, we **cannot wait for a timeout** and then decode the protocol as IRremote does.
@@ -699,7 +699,7 @@ However, **interrupts are explicitly enabled here** to allow the use of delay() Check out the [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) and [IRDispatcherDemo](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#irdispatcherdemo) examples.
Take care to include `TinyIRReceiver.hpp` or `TinyIRSender.hpp` instead of `IRremote.hpp`. -The **TinyIRSender** generates its 38 kHz signal by **[bit banging](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/TinyIRSender.hpp#L68)** using the `delayMicroseconds()` and `micros()` functions. +The **TinyIRSender** generates its 38 kHz PWM signal by **[software bit banging](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/TinyIRSender.hpp#L68)** using the `delayMicroseconds()` and `micros()` functions. ### TinyIRReceiver usage ```c++ @@ -708,12 +708,12 @@ The **TinyIRSender** generates its 38 kHz signal by **[bit banging](https://gith #include "TinyIRReceiver.hpp" void setup() { - initPCIInterruptForTinyReceiver(); // Enables the interrupt generation on change of IR input signal + initPCIInterruptForTinyIRReceiver(); // Enables the interrupt generation on change of IR input signal } void loop() { - if (TinyReceiverDecode()) { - printTinyReceiverResultMinimal(&Serial); + if (TinyIRReceiverDecode()) { + printTinyIRReceiverResultMinimal(&Serial); } // No resume() required :-) } @@ -882,7 +882,7 @@ This is often due to **timer resource conflicts** with the other library. Please ## 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 requires no polling, works down to 1 MHz.
+The TinyIRReceiver, which requires no polling, works down to 1 MHz.
For sending, the **minimal CPU clock frequency for software generated PWM is 8 MHz**. You can switch to timer and hardware PWM generation at fixed pins by `#define SEND_PWM_BY_TIMER`. ### Hardware PWM generation of sending signal with 8 bit timer @@ -890,6 +890,7 @@ You can switch to timer and hardware PWM generation at fixed pins by `#define SE - 8 MHZ F_CPU and 38 kHz -> no prescaling , divider = 210.526 -> 38.1 kHz with divider 210 - 4 MHZ F_CPU and 38 kHz -> no prescaling , divider = 105.26 -> 38.1 kHz with divider 105 - 1 MHZ F_CPU and 38 kHz -> no prescaling , divider = 26.31 -> 38.4 kHz with divider 36 +TinyIRSender does not support hardware PWM generation. ## Bang & Olufsen protocol The Bang & Olufsen protocol decoder is not enabled by default, i.e if no protocol is enabled explicitly by #define `DECODE_`. It must always be enabled explicitly by `#define DECODE_BEO`. @@ -1073,7 +1074,7 @@ These macros must be defined in your program before the line `#include ` to take effect. | Name | Default value | Description | |-|-:|-| -| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. | +| `USE_TINY_IR_RECEIVER` | disabled | Use [TinyIRReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tinyreceiver--tinysender) for receiving IR codes. | | `IR_COMMAND_HAS_MORE_THAN_8_BIT` | disabled | Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry. | | `IR_ADDRESS` | empty | If set, compare the address returned by the IR library with this value before executing a command. | | `DISPATCHER_BUZZER_FEEDBACK_PIN` | | If `USE_TINY_IR_RECEIVER` is enabled, the pin to be used for the optional 50 ms buzzer feedback before executing a command. Other IR libraries than Tiny are not compatible with tone() command. | @@ -1193,8 +1194,8 @@ 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. +### Use NEC protocol and TinyIRReceiver +[TinyIRReceiver](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tiny-nec-receiver-and-sender) does not require a timer, it relies on interrupts, thus avoiding any timer resource problems. ### Change timer The best approach is to **change the timer** used for IRremote, which can be accomplished by specifying the timer before `#include `.
diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 65d1da19f..079600b72 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -88,7 +88,7 @@ void setup() { Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR)); // Enables the interrupt generation on change of IR input signal - if (!initPCIInterruptForTinyReceiver()) { + if (!initPCIInterruptForTinyIRReceiver()) { Serial.println(F("No interrupt available for pin " STR(IR_RECEIVE_PIN))); // optimized out by the compiler, if not required :-) } #if defined(USE_FAST_PROTOCOL) @@ -99,7 +99,7 @@ void setup() { } void loop() { - if (TinyReceiverDecode()) { + if (TinyIRReceiverDecode()) { /* * The library has already copied the data used for this output, * so there is no need to do this in the callback function. @@ -156,7 +156,7 @@ void handleReceivedTinyIRData() { */ # else // As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon - printTinyReceiverResultMinimal(&Serial); + printTinyIRReceiverResultMinimal(&Serial); # endif if (TinyIRReceiverData.Command == 0x10) { // do something SHORT here diff --git a/src/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp index c82d99c8f..bbc104197 100644 --- a/src/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -74,10 +74,10 @@ IRCommandDispatcher IRDispatcher; #include "LocalDebugLevelStart.h" void IRCommandDispatcher::init() { - initPCIInterruptForTinyReceiver(); + initPCIInterruptForTinyIRReceiver(); } /* - * This is the TinyReceiver callback function, which is called if a complete command was received. + * This is the TinyIRReceiver callback function, which is called if a complete command was received. * Interrupts are enabled here to allow e.g. delay() in commands. * Copy the (volatile) IR data in order not to be overwritten on receiving of next frame. * Next, check for right address if IR_ADDRESS is defined. @@ -93,7 +93,7 @@ void handleReceivedTinyIRData() { IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); # if defined(LOCAL_INFO) - printTinyReceiverResultMinimal(&Serial); + printTinyIRReceiverResultMinimal(&Serial); # endif # if defined(IR_ADDRESS) diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 6f99f6c76..84d039762 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -44,6 +44,8 @@ #endif #if defined(F_CPU) // F_CPU is used to generate the receive send timings in some CPU's #define CLOCKS_PER_MICRO (F_CPU / MICROS_IN_ONE_SECOND) +#else +#define CLOCKS_PER_MICRO 48 // just a guess if F_CPU is not specified #endif /* diff --git a/src/TinyIR.h b/src/TinyIR.h index 19845d02d..d26a31331 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -30,13 +30,13 @@ #include "LongUnion.h" -/** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol +/** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol * @{ */ -#define VERSION_TINYIR "2.2.0" +#define VERSION_TINYIR "2.3.0" #define VERSION_TINYIR_MAJOR 2 -#define VERSION_TINYIR_MINOR 2 +#define VERSION_TINYIR_MINOR 3 #define VERSION_TINYIR_PATCH 0 // The change log is at the bottom of the file @@ -198,7 +198,7 @@ extern void handleReceivedTinyIRData(); #define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4 #define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5 /** - * Control and data variables of the state machine for TinyReceiver + * Control and data variables of the state machine for TinyIRReceiver */ struct TinyIRReceiverStruct { /* @@ -247,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 / TinyReceiverDecode(), to avoid multiple evaluations of the same IR frame. + bool justWritten; ///< Is set true if new data is available. Used by the main loop / TinyIRReceiverDecode(), to avoid multiple evaluations of the same IR frame. }; extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; @@ -259,6 +259,15 @@ bool isTinyReceiverIdle(); bool TinyReceiverDecode(); void printTinyReceiverResultMinimal(Print *aSerial); +bool isIRReceiverAttachedForTinyIRReceiver(); +bool initPCIInterruptForTinyIRReceiver(); +bool enablePCIInterruptForTinyIRReceiver(); +void disablePCIInterruptForTinyIRReceiver(); +bool isTinyIRReceiverIdle(); +bool TinyIRReceiverDecode(); +void printTinyIRReceiverResultMinimal(Print *aSerial); + + void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100 @@ -281,6 +290,9 @@ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin #endif /* + * Version 2.3.0 - 3/2026 + * - Renamed TinyReceiver*() functions to TinyIRReceiver*(). + * * Version 2.2.0 - 7/2024 * - New TinyReceiverDecode() function to be used as drop in for IrReceiver.decode(). * diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index b2f313f59..a378fa1b8 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -85,7 +85,7 @@ #include "TinyIR.h" #include "digitalWriteFast.h" -/** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol +/** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol * @{ */ @@ -424,37 +424,46 @@ void IRPinChangeInterruptHandler(void) { #endif } -bool isTinyReceiverIdle() { +bool isTinyIRReceiverIdle() { return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK); } +bool isTinyReceiverIdle() { + return isTinyIRReceiverIdle(); +} /* * Function to be used as drop in for IrReceiver.decode() */ -bool TinyReceiverDecode() { +bool TinyIRReceiverDecode() { bool tJustWritten = TinyIRReceiverData.justWritten; if (tJustWritten) { TinyIRReceiverData.justWritten = false; } return tJustWritten; } +bool TinyReceiverDecode() { + return TinyIRReceiverDecode(); +} /* * Checks if IR_RECEIVE_PIN is connected and high * @return true, if IR Receiver is attached */ -bool isIRReceiverAttachedForTinyReceiver() { +bool isIRReceiverAttachedForTinyIRReceiver() { pinModeFast(IR_RECEIVE_PIN, OUTPUT); digitalWriteFast(IR_RECEIVE_PIN, LOW); // discharge pin capacity pinModeFast(IR_RECEIVE_PIN, INPUT); return digitalRead(IR_RECEIVE_PIN); // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast. } +bool isIRReceiverAttachedForTinyReceiver() { + return isIRReceiverAttachedForTinyIRReceiver(); +} /** * Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode. - * Then call enablePCIInterruptForTinyReceiver() + * Then call enablePCIInterruptForTinyIRReceiver() */ -bool initPCIInterruptForTinyReceiver() { +bool initPCIInterruptForTinyIRReceiver() { pinModeFast(IR_RECEIVE_PIN, INPUT); #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) @@ -465,8 +474,11 @@ bool initPCIInterruptForTinyReceiver() { #endif return enablePCIInterruptForTinyReceiver(); } +bool initPCIInterruptForTinyReceiver() { + return initPCIInterruptForTinyIRReceiver(); +} -void printTinyReceiverResultMinimal(Print *aSerial) { +void printTinyIRReceiverResultMinimal(Print *aSerial) { // Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon #if defined(USE_FAST_PROTOCOL) aSerial->print(F("C=0x")); @@ -486,6 +498,9 @@ void printTinyReceiverResultMinimal(Print *aSerial) { #endif aSerial->println(); } +void printTinyReceiverResultMinimal(Print *aSerial) { + printTinyIRReceiverResultMinimal(aSerial); +} #if !defined(STR_HELPER) && !defined(STR) // Helper macro for getting a macro definition as string @@ -566,7 +581,7 @@ void printTinyReceiverResultMinimal(Print *aSerial) { * Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt() function. * @return true if interrupt was successfully enabled */ -bool enablePCIInterruptForTinyReceiver() { +bool enablePCIInterruptForTinyIRReceiver() { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif @@ -636,8 +651,11 @@ bool enablePCIInterruptForTinyReceiver() { #endif // defined(USE_ATTACH_INTERRUPT) return true; } +bool enablePCIInterruptForTinyReceiver() { + return enablePCIInterruptForTinyIRReceiver(); +} -void disablePCIInterruptForTinyReceiver() { +void disablePCIInterruptForTinyIRReceiver() { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif @@ -678,6 +696,9 @@ void disablePCIInterruptForTinyReceiver() { # endif #endif // defined(USE_ATTACH_INTERRUPT) } +void disablePCIInterruptForTinyReceiver() { + disablePCIInterruptForTinyIRReceiver(); +} /* * Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores. From b40476b8443decb6ad97c1b96da0d4d1cbae1466 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 18 Mar 2026 01:03:34 +0100 Subject: [PATCH 126/133] Bumped version to 4.7.0. -Fixed bug in sending RC6A, updated LG protocol and removed useless LG2 protocol, added new functions match*WithGreaterRange(), improved B&O decoding --- README.md | 1 + changelog.md | 5 + .../AllProtocolsOnLCD/AllProtocolsOnLCD.ino | 22 ++- examples/ReceiveDemo/ReceiveDemo.ino | 1 + examples/SendLGAirConditionerDemo/Readme.md | 93 ---------- .../SendLGAirConditionerDemo.ino | 5 +- examples/UnitTest/UnitTest.ino | 122 +++++++++++-- examples/UnitTest/UnitTest.log | 94 ++++++++-- keywords.txt | 8 +- library.json | 2 +- library.properties | 4 +- src/IRProtocol.h | 6 +- src/IRProtocol.hpp | 3 +- src/IRReceive.hpp | 96 ++++++++-- src/IRSend.hpp | 2 +- src/IRVersion.h | 6 +- src/IRremoteInt.h | 11 +- src/ac_LG.h | 1 - src/ac_LG.hpp | 2 +- src/ir_BangOlufsen.hpp | 78 +++++--- src/ir_DistanceWidthProtocol.hpp | 2 +- src/ir_JVC.hpp | 10 +- src/ir_LG.hpp | 85 ++++----- src/ir_Lego.hpp | 3 +- src/ir_NEC.hpp | 10 +- src/ir_OpenLASIR.hpp | 10 +- src/ir_RC5_RC6.hpp | 167 +++++++++++++----- src/ir_Samsung.hpp | 10 +- src/ir_Sony.hpp | 12 +- src/private/IRTimer.hpp | 1 + 30 files changed, 548 insertions(+), 324 deletions(-) delete mode 100644 examples/SendLGAirConditionerDemo/Readme.md diff --git a/README.md b/README.md index 75a4676eb..70f0fbaa2 100644 --- a/README.md +++ b/README.md @@ -1035,6 +1035,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `MARK_EXCESS_MICROS` | 20 | MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, to compensate for the signal forming of different IR receiver modules. Is set to 20 if `DO_NOT_USE_THRESHOLD_DECODER` is enabled. | | `RECORD_GAP_MICROS` | 5000 | Minimum gap between IR transmissions, to detect the end of a protocol.
Must be greater than any space of a protocol e.g. the NEC header space of 4500 µs.
Must be smaller than any gap between a command and a repeat; e.g. the retransmission gap for Sony is around 24 ms.
Keep in mind, that this is the delay between the end of the received command and the start of decoding. | | `DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE` | 50 if RAM <= 2k, else 200 | A value of 200 allows to decode mark or space durations up to 10 ms. | +| `SHOW_DISTANCE_WIDTH_DECODER_ERRORS` | disabled | Prints the reason which prevents data to be decoded as distance width data. | | `IR_INPUT_IS_ACTIVE_HIGH` | disabled | Enable it if you use a RF receiver, which has an active HIGH output signal. | | `IR_SEND_PIN` | disabled | If specified, it reduces program size and improves send timing for AVR. If you want to use a variable to specify send pin e.g. with `setSendPin(uint8_t aSendPinNumber)`, you must not use / disable this macro in your source. | | `SEND_PWM_BY_TIMER` | disabled | Disables carrier PWM generation in software and use hardware PWM (by timer). Has the **advantage of more exact PWM generation**, especially the duty cycle (which is not very relevant for most IR receiver circuits), and the **disadvantage of using a hardware timer**, which in turn is not available for other libraries and to fix the send pin (but not the receive pin) at the [dedicated timer output pin(s)](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#timer-and-pin-usage). Is enabled for ESP32 and RP2040 in all examples, since they support PWM generation for each pin without using a shared resource (timer). | diff --git a/changelog.md b/changelog.md index 3943cf16f..cfce902b8 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,11 @@ See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-I # 4.6.2 - Added removed typedef `IRRawDataType` for backward compatibility. +- Modified and renamed function `setToggleBitValueForRC5AndRC6()` to `setNextToggleBitValueForRC5AndRC6()`. +- Fixed bug in sending RC6A. +- Updated `LG` protocol and removed useless `LG2` protocol. +- Added new functions `match*WithGreaterRange()`, e.g. `matchMarkWithGreaterRange()`. +- Improved B&O decoding using new functions. # 4.6.1 - Fixed bug #1347 in RC5/RC6 autorepeat bit handling. Thanks to Craig Leres. diff --git a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino index bf86a092e..62a8a9282 100644 --- a/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino +++ b/examples/AllProtocolsOnLCD/AllProtocolsOnLCD.ino @@ -9,7 +9,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -66,7 +66,7 @@ // 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 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. @@ -162,18 +162,16 @@ void setup() { #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. Serial.println(); - Serial.print(F("If you connect debug pin ")); -# if defined(APPLICATION_PIN_STRING) - Serial.print(APPLICATION_PIN_STRING); -# else - Serial.print(DEBUG_BUTTON_PIN); -# endif - Serial.print(F(" to ground")); + if (digitalRead(DEBUG_BUTTON_PIN) != LOW) { + Serial.print(F("If you connect debug pin ")); + Serial.print(DEBUG_BUTTON_PIN); + Serial.print(F(" to ground")); # if defined(AUXILIARY_DEBUG_BUTTON_PIN) - Serial.print(F(" or to pin ")); - Serial.print(AUXILIARY_DEBUG_BUTTON_PIN); + Serial.print(F(" or to pin ")); + Serial.print(AUXILIARY_DEBUG_BUTTON_PIN); #endif - Serial.println(F(", raw data is always printed")); + Serial.println(F(", raw data is always printed")); + } // Info for receive Serial.print(RECORD_GAP_MICROS); diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index bcfac1b82..2cd0eedc5 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -99,6 +99,7 @@ //#define USE_THRESHOLD_DECODER // May give slightly better results especially for jittering signals and protocols with short 1 pulses / pauses. Requires additional 1 bytes program memory. //#define IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK // saves 32 bytes program memory //#define USE_16_BIT_TIMING_BUFFER // Use a 16-bit buffer to preserve values above 12750 us +#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints the reason which prevents data to be decoded as distance width data // MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding, // to compensate for the signal forming of different IR receiver modules. See also IRremote.hpp line 135. diff --git a/examples/SendLGAirConditionerDemo/Readme.md b/examples/SendLGAirConditionerDemo/Readme.md deleted file mode 100644 index ad16367c0..000000000 --- a/examples/SendLGAirConditionerDemo/Readme.md +++ /dev/null @@ -1,93 +0,0 @@ -=== decoding for LG A/C ==== -- 1) remote of LG AC has two type of HDR mark/space, 8000/4000 and 3100/10000 -- 2) HDR 8000/4000 is decoded using decodeLG(IRrecvDumpV2) without problem -- 3) for HDR 3100/10000, use AnalysIR's code : http://www.analysir.com/blog/2014/03/19/air-conditioners-problems-recording-long-infrared-remote-control-signals-arduino/ -- 4) for bin output based on AnalysIR's code : https://gist.github.com/chaeplin/a3a4b4b6b887c663bfe8 -- 5) remove first two byte(11) -- 6) sample rawcode with bin output : https://gist.github.com/chaeplin/134d232e0b8cfb898860 - - -=== *** === -- 1) Sample raw code : https://gist.github.com/chaeplin/ab2a7ad1533c41260f0d -- 2) send raw code : https://gist.github.com/chaeplin/7c800d3166463bb51be4 - - -=== *** === -- (0) : Cooling or Heating -- (1) : fixed address -- (2) : fixed address -- (3) : special(power, swing, air clean) -- (4) : change air flow, temperature, cooling(0)/heating(4) -- (5) : temperature ( 15 + (5) = ) -- (6) : air flow -- (7) : checksum ( 3 + 4 + 5 + 6 ) & B00001111 - - -°F = °C × 1.8 + 32
-°C = (°F - 32) / 1.8 - - -=== *** === -* remote / Korea / without heating - -| status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7) -|----------------|---|----|----|----|----|----|----|---- -| on / 25 / mid | C |1000|1000|0000|0000|1010|0010|1100 -| on / 26 / mid | C |1000|1000|0000|0000|1011|0010|1101 -| on / 27 / mid | C |1000|1000|0000|0000|1100|0010|1110 -| on / 28 / mid | C |1000|1000|0000|0000|1101|0010|1111 -| on / 25 / high | C |1000|1000|0000|0000|1010|0100|1110 -| on / 26 / high | C |1000|1000|0000|0000|1011|0100|1111 -| on / 27 / high | C |1000|1000|0000|0000|1100|0100|0000 -| on / 28 / high | C |1000|1000|0000|0000|1101|0100|0001 -|----------------|---|----|----|----|----|----|----|---- -| 1 up | C |1000|1000|0000|1000|1101|0100|1001 -|----------------|---|----|----|----|----|----|----|---- -| Cool power | C |1000|1000|0001|0000|0000|1100|1101 -| energy saving | C |1000|1000|0001|0000|0000|0100|0101 -| power | C |1000|1000|0001|0000|0000|1000|1001 -| flow/up/down | C |1000|1000|0001|0011|0001|0100|1001 -| up/down off | C |1000|1000|0001|0011|0001|0101|1010 -| flow/left/right| C |1000|1000|0001|0011|0001|0110|1011 -| left/right off | C |1000|1000|0001|0011|0001|0111|1100 -|----------------|---|----|----|----|----|----|----|---- -| Air clean | C |1000|1000|1100|0000|0000|0000|1100 -|----------------|---|----|----|----|----|----|----|---- -| off | C |1000|1000|1100|0000|0000|0101|0001 - - - -* remote / with heating -* converted using raw code at https://github.com/chaeplin/RaspAC/blob/master/lircd.conf - -| status |(0)| (1)| (2)| (3)| (4)| (5)| (6)| (7) -|----------------|---|----|----|----|----|----|----|---- -| on | C |1000|1000|0000|0000|1011|0010|1101 -|----------------|---|----|----|----|----|----|----|---- -| off | C |1000|1000|1100|0000|0000|0101|0001 -|----------------|---|----|----|----|----|----|----|---- -| 64 / 18 | C |1000|1000|0000|0000|0011|0100|0111 -| 66 / 19 | C |1000|1000|0000|0000|0100|0100|1000 -| 68 / 20 | C |1000|1000|0000|0000|0101|0100|1001 -| 70 / 21 | C |1000|1000|0000|0000|0110|0100|1010 -| 72 / 22 | C |1000|1000|0000|0000|0111|0100|1011 -| 74 / 23 | C |1000|1000|0000|0000|1000|0100|1100 -| 76 / 25 | C |1000|1000|0000|0000|1010|0100|1110 -| 78 / 26 | C |1000|1000|0000|0000|1011|0100|1111 -| 80 / 27 | C |1000|1000|0000|0000|1100|0100|0000 -| 82 / 28 | C |1000|1000|0000|0000|1101|0100|0001 -| 84 / 29 | C |1000|1000|0000|0000|1110|0100|0010 -| 86 / 30 | C |1000|1000|0000|0000|1111|0100|0011 -|----------------|---|----|----|----|----|----|----|---- -| heat64 | H |1000|1000|0000|0100|0011|0100|1011 -| heat66 | H |1000|1000|0000|0100|0100|0100|1100 -| heat68 | H |1000|1000|0000|0100|0101|0100|1101 -| heat70 | H |1000|1000|0000|0100|0110|0100|1110 -| heat72 | H |1000|1000|0000|0100|0111|0100|1111 -| heat74 | H |1000|1000|0000|0100|1000|0100|0000 -| heat76 | H |1000|1000|0000|0100|1001|0100|0001 -| heat78 | H |1000|1000|0000|0100|1011|0100|0011 -| heat80 | H |1000|1000|0000|0100|1100|0100|0100 -| heat82 | H |1000|1000|0000|0100|1101|0100|0101 -| heat84 | H |1000|1000|0000|0100|1110|0100|0110 -| heat86 | H |1000|1000|0000|0100|1111|0100|0111 diff --git a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino index b32dcc95f..d5282f348 100644 --- a/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino +++ b/examples/SendLGAirConditionerDemo/SendLGAirConditionerDemo.ino @@ -35,13 +35,12 @@ //#define NO_LED_FEEDBACK_CODE // Saves 276 bytes program memory /* - * LG2 has different header timing and a shorter bit time - * Known LG remote controls, which uses LG2 protocol are: + * LG has different header timing and a shorter bit time + * Known LG remote controls, which uses LG protocol are: * AKB75215403 * AKB74955603 * AKB73757604: */ -//#define USE_LG2_PROTOCOL // Try it if you do not have success with the default LG protocol #define NUMBER_OF_COMMANDS_BETWEEN_PRINT_OF_MENU 5 #if !defined(ARDUINO_ESP32C3_DEV) // This is due to a bug in RISC-V compiler, which requires unused function sections :-(. diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index d28d0fafa..f03dbb895 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -65,7 +65,7 @@ // 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 MARK_EXCESS_MICROS 40 // 40 inhibits the decoding of the short B&O marks of 250 us. //#define RECORD_GAP_MICROS 12000 // Default is 8000. Activate it for some LG air conditioner protocols. @@ -113,7 +113,7 @@ //#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 +#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints the reason which prevents data to be decoded as distance width data #include #include "TinyIRSender.hpp" @@ -528,7 +528,7 @@ void loop() { checkReceive(sAddress, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send NEC2 with 16 bit address")); + Serial.println(F("Send NEC2 with 16 bit address")); // The only difference is the repeat Serial.flush(); IrSender.sendNEC2(sAddress, sCommand, sRepeats); checkReceive(sAddress, sCommand); @@ -540,6 +540,57 @@ void loop() { /* * Do this only once at the first loop */ + +#if defined(DECODE_RC5) + /* + * Test minimal RC5X and maximal RC5 length + */ + Serial.println(F("Send RC5 minimal length")); // 14 + Serial.flush(); + IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get minimal length + IrSender.sendRC5(0x0A, 0x6A, sRepeats, true); // use RC5X + checkReceive(0x0A, 0x6A); + delay(DELAY_AFTER_SEND / 2); + + Serial.println(F("Send RC5 maximal length")); // 28 + Serial.flush(); + IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get maximal length + IrSender.sendRC5(0x1F, 0x3F, sRepeats, true); + checkReceive(0x1F, 0x3F); + delay(DELAY_AFTER_SEND / 2); + + Serial.println(F("Send Marantz maximal length")); // 34 + Serial.flush(); + IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get maximal length + IrSender.sendRC5Marantz(0x1F, 0x3F, sRepeats, 0x3F, true); + if (checkReceive(0x1F, 0x3F)) { + checkReceivedExtra(0x3F); + } + + delay(DELAY_AFTER_SEND); +#endif // defined(DECODE_RC5) + +#if defined(DECODE_RC6) + /* + * Test minimal RC6 and maximal RC6A length + * Toggle bit does not make any difference for RC6A, because it is located between a 0 and a 1 bit + */ + Serial.println(F("Send RC6 minimal length")); // 26 + Serial.flush(); + IrSender.setNextToggleBitValueForRC5AndRC6(1); // To get minimal length + IrSender.sendRC6(0x55, 0x55, 0, true); + checkReceive(0x55, 0x55); + delay(DELAY_AFTER_SEND / 2); + + Serial.println(F("Send RC6A maximal length")); // 72 + Serial.flush(); + IrSender.sendRC6A(0xFF, 0xFF, 0, 0x3FFF, true); + if (checkReceive(0xFF, 0xFF)) { + checkReceivedExtra(0x3FFF); + } + delay(DELAY_AFTER_SEND); +#endif // defined(DECODE_RC6) + IRDecodedRawDataType tRawData[4]; /* @@ -705,6 +756,31 @@ void loop() { # endif delay(DELAY_AFTER_SEND); + /* + * This one can be interpreted as 52 bit PulseDistance or 53 bit PulseWidth with inverted bits and bit timing. + Protocol=PulseWidth, Raw-Data=0x123456, 53 bits, LSB first, Gap=789450us, Duration=49100us + Send on a 8 bit platform with: + uint32_t tRawData[]={0x789ABCDE, 0x123456}; + IrSender.sendPulseDistanceWidthFromArray(38, 300, 650, 600, 450, 300, 450, &tRawData[0], 53, PROTOCOL_IS_LSB_FIRST, , ); + rawIRTimings[108]: + -789450 + + 300,- 650 + + 300,- 600 + 600,- 300 + 650,- 450 + 500,- 250 + + 600,- 300 + 300,- 650 + 650,- 250 + 600,- 350 + + 250,- 650 + 300,- 600 + 650,- 250 + 650,- 300 + + 600,- 350 + 550,- 300 + 350,- 550 + 650,- 300 + + 300,- 650 + 550,- 300 + 350,- 550 + 650,- 300 + + 600,- 300 + 350,- 550 + 300,- 600 + 650,- 350 + + 300,- 600 + 250,- 600 + 350,- 600 + 600,- 300 + + 650,- 300 + 600,- 250 + 600,- 300 + 350,- 600 + + 300,- 650 + 600,- 300 + 650,- 250 + 350,- 550 + + 550,- 350 + 300,- 650 + 600,- 300 + 300,- 600 + + 300,- 600 + 350,- 600 + 650,- 250 + 350,- 550 + + 650,- 300 + 650,- 250 + 300,- 600 + 350,- 550 + + 350,- 600 + 650,- 250 + 350,- 550 + 350,- 550 + + 650 + Duration=49100us + */ Serial.println(F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first 1=300|600, 0=600|300")); Serial.flush(); // Real PulseDistanceWidth (constant bit length) does theoretically not require a stop bit, but we know the stop bit from serial transmission @@ -719,7 +795,8 @@ void loop() { delay(DELAY_AFTER_SEND); Serial.println( - F("Send 52 bit PulseDistanceWidth 0xDCBA9 87654321 LSB first with inverse timing and data 1=600|300, 0=300|600")); + F( + "Send the same 52 bit PulseDistanceWidth but with inverse of 0xDCBA9 87654321 and with inverse timing 1=600|300, 0=300|600")); Serial.flush(); # if __INT_WIDTH__ < 32 tRawData[2] = ~tRawData[0]; @@ -804,11 +881,13 @@ void loop() { # endif // defined(DECODE_MAGIQUEST) } // end of once at first loop +# if defined(DECODE_NEC) Serial.println(F("Send NEC with TinyIRSender")); Serial.flush(); sendNEC(IR_SEND_PIN, (uint8_t) sAddress, sCommand, sRepeats); // Casting saves 18 bytes checkReceive(sAddress & 0xFF, sCommand); delay(DELAY_AFTER_SEND); +# endif # if defined(DECODE_FAST) Serial.println(F("Send FAST with TinyIRSender")); @@ -863,7 +942,7 @@ void loop() { checkReceive(sAddress & 0x1F, sCommand); delay(DELAY_AFTER_SEND); - Serial.println(F("Send Denon/Sharp variant with 2 autorepeat5 after 45 ms")); + Serial.println(F("Send Denon/Sharp variant with 2 autorepeats after 45 ms")); Serial.flush(); IrSender.sendSharp(sAddress & 0x1F, sCommand, sRepeats); checkReceive(sAddress & 0x1F, sCommand); @@ -923,6 +1002,10 @@ void loop() { delay(DELAY_AFTER_SEND); #endif +#if defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6) + IrSender.setNextToggleBitValueForRC5AndRC6(sCommand); // To modify start value of toggling for each loop. Only LSB is taken :-). +#endif + #if defined(DECODE_RC5) Serial.println(F("Send RC5")); Serial.flush(); @@ -960,7 +1043,6 @@ void loop() { #if defined(DECODE_RC6) Serial.println(F("Send RC6")); Serial.flush(); - IrSender.setToggleBitValueForRC5AndRC6(sAddress); // To modify start value of toggling for each loop. Only LSB is taken :-). IrSender.sendRC6(sAddress & 0xFF, sCommand, sRepeats, true); checkReceive(sAddress & 0xFF, sCommand); @@ -1005,9 +1087,9 @@ void loop() { #endif #if defined(DECODE_BEO) - Serial.println(F("Send 16 bit Bang&Olufsen / originally with 455 kHz")); + Serial.println(F("Send 16 bit Bang&Olufsen - requires originally 455 kHz")); Serial.flush(); - IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats); // send 8 bit command and 8 bit address / header + IrSender.sendBangOlufsen(sAddress, sCommand, sRepeats, 8); // send 8 bit command and 8 bit address / header # if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) delay((RECORD_GAP_MICROS / 1000) + 1); Serial.println(F("- ENABLE_BEO_WITHOUT_FRAME_GAP is enabled")); @@ -1022,19 +1104,21 @@ void loop() { 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 - Serial.println(); - Serial.println( - F( - "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode")); - IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; - IrReceiver.irparams.rawlen = tOriginalRawlen - 6; - for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { - IrReceiver.irparams.rawbuf[i] = IrReceiver.irparams.rawbuf[i + 6]; + if (tOriginalRawlen > 30) { + // Remove trailing 6 entries for second decode try + Serial.println(); + Serial.println( + F( + "- Remove trailing 6 entries, which is equivalent to define RECORD_GAP_MICROS < 15000, to enable successful B&O decode")); + IrReceiver.decodedIRData.rawlen = tOriginalRawlen - 6; + IrReceiver.irparams.rawlen = tOriginalRawlen - 6; + for (uint_fast8_t i = 0; i < IrReceiver.decodedIRData.rawlen; ++i) { + IrReceiver.irparams.rawbuf[i] = IrReceiver.irparams.rawbuf[i + 6]; + } + IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0]; + checkReceive(sAddress & 0xFF, sCommand); // only 8 bit of address is sent } - IrReceiver.decodedIRData.initialGapTicks = IrReceiver.irparams.rawbuf[0]; # endif - checkReceive(sAddress & 0xFF, sCommand); // only 8 bit of address is sent delay(DELAY_AFTER_SEND); #endif diff --git a/examples/UnitTest/UnitTest.log b/examples/UnitTest/UnitTest.log index 9b089d256..4582eee2e 100644 --- a/examples/UnitTest/UnitTest.log +++ b/examples/UnitTest/UnitTest.log @@ -65,6 +65,74 @@ rawIRTimings[68]: Duration=73450us +Send RC5 minimal length +Protocol=RC5 Address=0xA, Command=0x6A, Toggle=1, Raw-Data=0xAAA, 13 bits, MSB first, Gap=765600us, Duration=23100us +Send with: IrSender.sendRC5(0xA, 0x6A, ); +rawIRTimings[14]: + -765600 + +1850,-1700 + +1850,-1700 +1850,-1700 +1850,-1700 +1850,-1700 + +1800,-1750 +1800 +Duration=23100us + + +Send RC5 maximal length +Protocol=RC5 Address=0x1F, Command=0x3F, Toggle=1, Raw-Data=0x1FFF, 13 bits, MSB first, Gap=391600us, Duration=24200us +Send with: IrSender.sendRC5(0x1F, 0x3F, ); +rawIRTimings[28]: + -391600 + + 900,- 900 + + 950,- 800 +1000,- 800 + 900,- 900 + 950,- 850 + + 900,- 850 + 950,- 850 + 900,- 900 + 900,- 900 + + 900,- 900 + 900,- 900 + 900,- 900 + 950,- 850 + + 900 +Duration=24200us + + +Send Marantz maximal length +Protocol=Marantz Address=0x1F, Command=0x3F, Extra=0x3F, Toggle=1, Raw-Data=0x7FFFF, 19 bits, MSB first, Gap=398900us, Duration=38350us +Send with: IrSender.sendMarantz(0x1F, 0x3F, , 0x3F); +rawIRTimings[40]: + -398900 + + 950,- 850 + + 850,- 950 + 900,- 900 + 950,- 850 + 950,- 800 + +1000,- 800 + 900,- 900 + 950,-4350 + 950,- 850 + + 950,- 800 +1000,- 800 + 850,- 950 + 950,- 850 + + 900,- 850 + 950,- 850 + 950,- 850 + 950,- 800 + +1000,- 800 + 950,- 850 + 850 +Duration=38350us + + +Send RC6 minimal length +Protocol=RC6 Address=0x55, Command=0x55, Toggle=1, Raw-Data=0x15555, 20 bits, MSB first, Gap=744250us, Duration=23100us +Send with: IrSender.sendRC6(0x55, 0x55, ); +rawIRTimings[26]: + -744250 + +2750,- 800 + + 550,- 800 + 500,- 400 + 500,- 450 +1400,-1250 + +1000,- 800 + 950,- 900 + 950,- 850 +1000,- 800 + + 950,- 850 + 950,- 900 +1000,- 800 +1000 +Duration=23100us + + +Send RC6A maximal length +Protocol=RC6A Address=0xFF, Command=0xFF, Extra=0x3FFF, Raw-Data=0x7FFFFFFF, 35 bits, MSB first, Gap=397100us, Duration=36850us +Send with: IrSender.sendRC6A(0xFF, 0xFF, , 0x3FFF); +rawIRTimings[72]: + -397100 + +2650,- 900 + + 550,- 400 + 400,- 500 + 500,- 850 + 500,- 850 + +1450,- 350 + 550,- 400 + 400,- 500 + 450,- 450 + + 500,- 400 + 550,- 400 + 400,- 500 + 450,- 450 + + 550,- 350 + 550,- 400 + 500,- 400 + 450,- 450 + + 500,- 400 + 500,- 450 + 400,- 500 + 450,- 450 + + 500,- 400 + 500,- 400 + 450,- 500 + 450,- 450 + + 500,- 400 + 550,- 350 + 450,- 500 + 450,- 450 + + 500,- 400 + 500,- 450 + 400,- 500 + 450,- 450 + + 450,- 450 + 550,- 350 + 500 +Duration=36850us + + Send arbitrary raw data with 1 repeat and exact timing (16 bit array format) with sendRaw() rawIRTimings[18]: -770450 @@ -776,7 +844,7 @@ rawIRTimings[36]: Duration=10250us -Send 16 bit Bang&Olufsen / originally with 455 kHz +Send 16 bit Bang&Olufsen - requires originally 455 kHz - ENABLE_BEO_WITHOUT_FRAME_GAP is enabled rawIRTimings[44]: -749450 @@ -823,20 +891,20 @@ Duration=40700us Send LG -Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745850us, Duration=59800us +Protocol=LG Address=0xF1, Command=0x9876, Raw-Data=0xF19876E, 28 bits, MSB first, Gap=745900us, Duration=59900us Send with: IrSender.sendLG(0xF1, 0x9876, ); rawIRTimings[60]: - -745850 - +8950,-4150 - + 550,-1500 + 550,-1550 + 550,-1550 + 550,-1500 - + 600,- 500 + 550,- 500 + 600,- 450 + 550,-1550 - + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550 - + 550,-1550 + 600,- 450 + 550,- 500 + 550,- 500 - + 550,- 550 + 550,-1550 + 550,-1500 + 600,-1500 - + 550,- 500 + 550,-1550 + 600,-1500 + 550,- 500 - + 600,-1500 + 550,-1550 + 550,-1500 + 600,- 500 + -745900 + +8350,-4150 + + 550,-1550 + 600,-1550 + 550,-1550 + 550,-1550 + + 600,- 550 + 500,- 550 + 550,- 550 + 550,-1550 + + 550,-1550 + 550,- 550 + 550,- 550 + 550,-1550 + + 550,-1550 + 550,- 550 + 550,- 550 + 550,- 550 + + 550,- 550 + 550,-1550 + 550,-1550 + 550,-1550 + + 550,- 550 + 550,-1550 + 550,-1550 + 550,- 550 + + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 550 + 550 -Duration=59800us +Duration=59900us Send Bosewave with no address and 8 command bits @@ -1407,7 +1475,7 @@ rawIRTimings[36]: Duration=10850us -Send 16 bit Bang&Olufsen / originally with 455 kHz +Send 16 bit Bang&Olufsen - requires originally 455 kHz - ENABLE_BEO_WITHOUT_FRAME_GAP is enabled rawIRTimings[86]: -749450 diff --git a/keywords.txt b/keywords.txt index 03bdd2891..ab15edd97 100644 --- a/keywords.txt +++ b/keywords.txt @@ -47,13 +47,14 @@ sendFAST KEYWORD2 sendJVC KEYWORD2 sendLegoPowerFunctions KEYWORD2 sendLG KEYWORD2 -sendLG2 KEYWORD2 -sendLG2Repeat KEYWORD2 +sendLGSpecialRepeat KEYWORD2 +sendLGRepeat KEYWORD2 sendLGRaw KEYWORD2 sendMaranz KEYWORD2 sendMagiQuest KEYWORD2 sendNEC KEYWORD2 sendNEC2 KEYWORD2 +sendNECSpecialRepeat KEYWORD2 sendNECRepeat KEYWORD2 sendNECRaw KEYWORD2 sendOnkyo KEYWORD2 @@ -67,6 +68,7 @@ sendKaseikyo_Mitsubishi KEYWORD2 sendRaw KEYWORD2 sendRaw_P KEYWORD2 sendRC5 KEYWORD2 +sendRC5Marantz KEYWORD2 sendRC6 KEYWORD2 sendSamsungRepeat KEYWORD2 sendSamsung KEYWORD2 @@ -74,6 +76,7 @@ sendSharp KEYWORD2 sendSony KEYWORD2 sendSharpRaw KEYWORD2 sendVelux KEYWORD2 +sendOpenLASIR KEYWORD2 # IRFeedbackLED disableLEDFeedback KEYWORD2 @@ -105,7 +108,6 @@ APPLE LITERAL1 DENON LITERAL1 JVC LITERAL1 LG LITERAL1 -LG2 LITERAL1 NEC LITERAL1 NEC2 LITERAL1 ONKYO LITERAL1 diff --git a/library.json b/library.json index b2e8660f4..56184158c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.6.2", + "version": "4.7.0", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index 1ada6ea35..e15d59b05 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=IRremote -version=4.6.2 +version=4.7.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, Velux, Universal Pulse Distance and Pulse Width. +paragraph=Currently included protocols: Denon / Sharp, JVC, LG, 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,riscv,nRF5 diff --git a/src/IRProtocol.h b/src/IRProtocol.h index e7527624a..eda5ad441 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -95,9 +95,9 @@ * !!!Must be the same order as ProtocolNames in IRProtocol.hpp!!! */ typedef enum { - UNKNOWN = 0, PULSE_WIDTH, PULSE_DISTANCE, APPLE, DENON, JVC, LG, LG2, NEC, NEC2, /* 10 entries */ - ONKYO, PANASONIC, KASEIKYO, KASEIKYO_DENON, KASEIKYO_SHARP, KASEIKYO_JVC, KASEIKYO_MITSUBISHI, RC5, RC6, RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ - SAMSUNG, /* 11 entries */ + UNKNOWN = 0, PULSE_WIDTH, PULSE_DISTANCE, APPLE, DENON, JVC, LG, NEC, NEC2, ONKYO, /* 10 entries */ + PANASONIC, KASEIKYO, KASEIKYO_DENON, KASEIKYO_SHARP, KASEIKYO_JVC, KASEIKYO_MITSUBISHI, RC5, RC6, RC6A, /*31 bit + 3 fixed 0b110 mode bits*/ + SAMSUNG, /* 10 entries */ SAMSUNGLG, SAMSUNG48, SHARP, SONY, /* Now the exotic protocols */ BANG_OLUFSEN, BOSEWAVE, LEGO_PF, MAGIQUEST, WHYNTER, MARANTZ,/* 10 entries */ diff --git a/src/IRProtocol.hpp b/src/IRProtocol.hpp index 7d2c5c455..18f145666 100644 --- a/src/IRProtocol.hpp +++ b/src/IRProtocol.hpp @@ -44,7 +44,6 @@ const char string_Apple[] PROGMEM = "Apple"; const char string_Denon[] PROGMEM = "Denon"; const char string_JVC[] PROGMEM = "JVC"; const char string_LG[] PROGMEM = "LG"; -const char string_LG2[] PROGMEM = "LG2"; const char string_NEC[] PROGMEM = "NEC"; const char string_NEC2[] PROGMEM = "NEC2"; const char string_Onkyo[] PROGMEM = "Onkyo"; @@ -76,7 +75,7 @@ const char string_Other[] PROGMEM = "OTHER"; * !!Must be the same order as in decode_type_t in IRProtocol.h!!! */ const char *const ProtocolNames[] -PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, string_LG2, +PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, 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_RC6A, string_Samsung, string_SamsungLG, string_Samsung48, string_Sharp, string_Sony diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 1732cff14..c281b31d1 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -35,6 +35,7 @@ // This block must be located after the includes of other *.hpp files //#define LOCAL_DEBUG // This enables debug output only for this file - only for development +//#define LOCAL_TRACE // This enables trace output only for this file - only for development #include "LocalDebugLevelStart.h" /* * Low level hardware timing measurement @@ -1230,12 +1231,12 @@ bool IRrecv::checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants bool IRrecv::checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM) { // Check header "mark" and "space" if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) { - TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); + TRACE_PRINT(::getProtocolString((decode_type_t ) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); TRACE_PRINTLN(F(": Header mark length is wrong")); return false; } if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) { - TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); + TRACE_PRINT(::getProtocolString((decode_type_t ) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex))); TRACE_PRINTLN(F(": Header space length is wrong")); return false; } @@ -1280,17 +1281,43 @@ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { 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 matchTicksWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { + uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK); + uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4; + + TRACE_PRINT(F("Testing with greater range (actual vs desired): ")); + TRACE_PRINT(tMeasuredMicros); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 2); // rounded value because we divide first + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 6); + + bool passed = (tMeasuredMicros >= (tMatchValueMicrosQuarter * 2) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 6)); +#if defined(LOCAL_TRACE) + if (passed) { + Serial.println(F(" => passed")); + } else { + Serial.println(F(" => FAILED")); + } +#endif + return passed; +} /** * Match function WITH compensating for marks exceeded or spaces shortened by demodulator hardware + * With MARK_EXCESS_MICROS default value of 20 we cannot match 200 to 250, because we have 186 < 180 <= 310 * @return true, if values match */ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks) { @@ -1304,20 +1331,47 @@ bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCo TRACE_PRINT(F("us: ")); TRACE_PRINT(tMatchValueMicrosQuarter * 3); // rounded value because we divide first TRACE_PRINT(F(" < ")); - TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK); + TRACE_PRINT(tMeasuredMicros); TRACE_PRINT(F(" <= ")); TRACE_PRINT(tMatchValueMicrosQuarter * 5); 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 matchTicksWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks) { + uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK) + aCompensationMicrosForTicks; + uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4; + + TRACE_PRINT(F("Testing with greater range (actual vs desired): ")); + TRACE_PRINT(tMeasuredMicros); + TRACE_PRINT(F("us vs ")); + TRACE_PRINT(aMatchValueMicros); + TRACE_PRINT(F("us: ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 2); // rounded value because we divide first + TRACE_PRINT(F(" < ")); + TRACE_PRINT(tMeasuredMicros); + TRACE_PRINT(F(" <= ")); + TRACE_PRINT(tMatchValueMicrosQuarter * 6); + + bool passed = (tMeasuredMicros > (tMatchValueMicrosQuarter * 2) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 6)); +#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); } @@ -1366,6 +1420,14 @@ bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { #endif } +bool matchMarkWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { +#if (MARK_EXCESS_MICROS == 0) + return matchTicksWithGreaterRange(aMeasuredTicks, aMatchValueMicros); +#else + return matchTicksWithGreaterRange(aMeasuredTicks, aMatchValueMicros, -MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors +#endif +} + bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) { return matchMark(measured_ticks, desired_us); } @@ -1412,6 +1474,14 @@ bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { #endif } +bool matchSpaceWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) { +#if (MARK_EXCESS_MICROS == 0) + return matchTicksWithGreaterRange(aMeasuredTicks, aMatchValueMicros); +#else + return matchTicksWithGreaterRange(aMeasuredTicks, aMatchValueMicros, MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors +#endif +} + bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) { return matchSpace(measured_ticks, desired_us); } diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 22cb84ef2..7aaa92c8f 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -1453,7 +1453,7 @@ void IRsend::IRLedOff() { /** * 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. + * Executing program between end of mark and start of next mark uses around 15 to 20 us @ 16 MHz. This time is added to the space delay here. */ void IRsend::space(uint16_t aSpaceMicros) { customDelayMicroseconds(aSpaceMicros); diff --git a/src/IRVersion.h b/src/IRVersion.h index f8ee19325..0a74f65d6 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.6.2" +#define VERSION_IRREMOTE "4.7.0" #define VERSION_IRREMOTE_MAJOR 4 -#define VERSION_IRREMOTE_MINOR 6 -#define VERSION_IRREMOTE_PATCH 2 +#define VERSION_IRREMOTE_MINOR 7 +#define VERSION_IRREMOTE_PATCH 0 /* * Macro to convert 3 version parts into an integer diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 84d039762..33910cf45 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -431,6 +431,10 @@ 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); +bool matchTicksWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros); +bool matchTicksWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks); +bool matchMarkWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros); +bool matchSpaceWithGreaterRange(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros); /* * Old function names @@ -623,10 +627,9 @@ class IRsend { void sendFAST(uint8_t aCommand, int_fast8_t aNumberOfRepeats); void sendJVC(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats); - void sendLG2Repeat(); + void sendLGRepeat(); uint32_t computeLGRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand); void sendLG(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); - void sendLG2(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats); void sendLGRaw(uint32_t aRawData, int_fast8_t aNumberOfRepeats = NO_REPEATS); void sendNECRepeat(); @@ -655,7 +658,7 @@ class IRsend { void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, int_fast8_t aNumberOfRepeats); // LSB first - void setToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue); + void setNextToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue); void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true); void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint8_t aMarantzExtension, bool aEnableAutomaticToggle = true); @@ -758,7 +761,7 @@ extern IRsend IrSender; void sendNECSpecialRepeat(); void sendOpenLASIRSpecialRepeat(); -void sendLG2SpecialRepeat(); +void sendLGSpecialRepeat(); void sendSamsungLGSpecialRepeat(); #endif // _IR_REMOTE_INT_H diff --git a/src/ac_LG.h b/src/ac_LG.h index 4f56de7b7..b19bea21f 100644 --- a/src/ac_LG.h +++ b/src/ac_LG.h @@ -131,7 +131,6 @@ class Aircondition_LG { uint8_t FanIntensity = 1; // 0 -> low, 4 high, 5 -> cycle uint8_t Temperature = 22; // temperature : 18 ~ 30 uint8_t Mode = AC_MODE_COOLING; - bool useLG2Protocol = false; }; /** @}*/ diff --git a/src/ac_LG.hpp b/src/ac_LG.hpp index 6e0b3730e..56d86321d 100644 --- a/src/ac_LG.hpp +++ b/src/ac_LG.hpp @@ -254,7 +254,7 @@ void Aircondition_LG::sendIRCommand(uint16_t aCommand) { INFO_PRINTLN(aCommand, BIN); - IrSender.sendLG2((uint8_t) LG_ADDRESS, aCommand, 0); + IrSender.sendLG((uint8_t) LG_ADDRESS, aCommand, 0); } /* diff --git a/src/ir_BangOlufsen.hpp b/src/ir_BangOlufsen.hpp index 041004a7f..de95898b4 100644 --- a/src/ir_BangOlufsen.hpp +++ b/src/ir_BangOlufsen.hpp @@ -50,11 +50,12 @@ // // //============================================================================== -// https://www.mikrocontroller.net/attachment/33137/datalink.pdf +// https://www.mikrocontroller.net/attachment/33137/datalink.pdf page 6 // https://www.mikrocontroller.net/articles/IRMP_-_english#B&O // BEO is a Pulse Distance Protocol with 200 us pulse // This protocol is unusual in two ways: // 1. The carrier frequency is 455 kHz +// // You can build your own receiver as Bang & Olufsen did (check old schematics) or use a TSOP7000 // Vishay stopped producing TSOP7000 since 2009 so you will probably only find counterfeits: // https://www.vishay.com/files/whatsnew/doc/ff_FastFacts_CounterfeitTSOP7000_Dec72018.pdf @@ -64,12 +65,15 @@ // Other examples may require a different treatment // This particular receiver also did receive lower frequencies but rather poorly and with a lower delay than usual // 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 // 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 // This treats the 3. start space of 15.5 ms as a gap between 2 messages, which makes decoding easier :-). @@ -80,16 +84,32 @@ // 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 !!! +// // IR messages are 16 bits long. Datalink messages have different lengths. // This implementation supports up to 40 bits total length split into 8 bit data/command and a header/address of variable length // Header data with more than 16 bits is stored in decodedIRData.extra // B&O is a pulse distance protocol, but it has 3 bit values 0, 1 and (equal/repeat) as well as a special start and trailing bit. // -// MSB first, 4 start bits + 8 (to 16?) bit address + 8 bit command + 1 special trailing bit + 1 stop bit. -// Address can be longer than 8 bit. +/* + 16 bit Bang&Olufsen, ENABLE_BEO_WITHOUT_FRAME_GAP is enabled + rawIRTimings[44]: + -749450 + + 250,-2850 + + 300,-2850 + 250,-12750 + 250,-2850 + 250,-9050 // 12750 is clipped big value of 15425 + + 250,-5950 + 250,-5950 + 300,-5950 + 250,-2850 + + 250,-5950 + 300,-5900 + 300,-9000 + 250,-2900 + + 250,-9050 + 250,-5950 + 300,-5900 + 300,-2850 + + 300,-9000 + 250,-5950 + 250,-2850 + 300,-12100 // +300, -12100 is trailing bit + + 300 // stop bit + Duration=134400us + + MSB first, 4 start bits + 8 (to 16?) bit address + 8 bit command + 1 special trailing bit + 1 stop bit. + 4 Start bits have the length 1, 1, 5, 1 and are +200 -2925, +200 -2925, +200 -15425, +200 -2925 + Address can be longer than 8 bit. + */ + /* * Options for this decoder - * */ #define ENABLE_BEO_WITHOUT_FRAME_GAP // Requires additional 30 bytes program memory. Enabled by default, see https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1181 //#define SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE // This also supports headers up to 32 bit. Requires additional 150 bytes program memory. @@ -113,7 +133,7 @@ // 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_BIT_MARK_FOR_DECODE 250 +#define BEO_BIT_MARK_FOR_DECODE 250 #define BEO_DATALINK_BIT_MARK (BEO_UNIT / 2) // The length of a mark in the Datalink protocol /* @@ -133,7 +153,7 @@ ************************************/ /* - * TODO aNumberOfRepeats are handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined + * TODO aNumberOfRepeats is handled not correctly if ENABLE_BEO_WITHOUT_FRAME_GAP is defined * By default 16 bits are sent. * @param aNumberOfHeaderBits default is 8, can be 24 at maximum */ @@ -188,14 +208,17 @@ void IRsend::sendBangOlufsenRaw(uint32_t aRawData, int_fast8_t aBits, bool aBack uint32_t mask = 1UL << (aBits - 1); for (; mask; mask >>= 1) { if (tLastBitValueWasOne && !(aRawData & mask)) { + // 1 to 0 transition mark(BEO_BIT_MARK); space(BEO_ZERO_SPACE - BEO_BIT_MARK); tLastBitValueWasOne = false; } else if (!tLastBitValueWasOne && (aRawData & mask)) { + // 0 to 1 transition mark(BEO_BIT_MARK); space(BEO_ONE_SPACE - BEO_BIT_MARK); tLastBitValueWasOne = true; } else { + // Both values are equal mark(BEO_BIT_MARK); space(BEO_REPETITION_OF_PREVIOUS_BIT_SPACE - BEO_BIT_MARK); } @@ -283,15 +306,15 @@ 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 + if (decodedIRData.rawlen != 6 && decodedIRData.rawlen < 38) { // 16 bits minimum DEBUG_PRINT(F("B&O: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); - DEBUG_PRINTLN(F(" is not < 36 or 6")); + DEBUG_PRINTLN(F(" is not 6 or not greater equal 38")); #else if (decodedIRData.rawlen < 44) { // 16 bits minimum DEBUG_PRINT(F("B&O: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); - DEBUG_PRINTLN(F(" is not < 44")); + DEBUG_PRINTLN(F(" is not greater equal 44")); #endif return false; } @@ -312,36 +335,41 @@ bool IRrecv::decodeBangOlufsen() { TRACE_PRINTLN(decodedIRData.rawlen); #if defined(ENABLE_BEO_WITHOUT_FRAME_GAP) - /* - * Check if we have the AGC part of the first frame, i.e. start bit 1 and 2. - */ if (decodedIRData.rawlen == 6) { - if ((matchMark(irparams.rawbuf[3], BEO_BIT_MARK_FOR_DECODE) || matchMark(irparams.rawbuf[3], BEO_DATALINK_BIT_MARK)) - && (matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_BIT_MARK_FOR_DECODE) - || matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_DATALINK_BIT_MARK))) { + /* + * Here we have the AGC part of the "Break at start mode" i.e. start bit 1 and 2. + * Test start bit 2 using IR or Datalink timing + */ + if ((matchMarkWithGreaterRange(irparams.rawbuf[3], BEO_BIT_MARK_FOR_DECODE) + && (matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_BIT_MARK_FOR_DECODE))) + || (matchMark(irparams.rawbuf[3], BEO_DATALINK_BIT_MARK) + && matchSpace(irparams.rawbuf[4], BEO_ZERO_SPACE - BEO_DATALINK_BIT_MARK))) { TRACE_PRINTLN(F("B&O: AGC only part (start bits 1 + 2 of 4) detected")); } else { - return false; // no B&O protocol + DEBUG_PRINTLN(F("B&O: No AGC only part (start bits 1 + 2 of 4) detected")); + DEBUG_PRINT(F("matchMarkWithGreaterRange([3], 250)=")); + DEBUG_PRINTLN(matchMarkWithGreaterRange(irparams.rawbuf[3], BEO_BIT_MARK_FOR_DECODE)); + return false; } } else { /* - * Check if leading gap is trailing bit of first AGC frame + * Check if leading gap is the start bit space we interpret as gap in "Break at start mode" */ if (!matchSpace(decodedIRData.initialGapTicks, BEO_START_BIT_SPACE)) { - TRACE_PRINT(F("B&O: Leading gap of ")); // Leading gap is trailing bit of first frame - TRACE_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); // Leading gap is trailing bit of first frame - TRACE_PRINTLN(F(" us is wrong")); // Leading gap is trailing bit of first frame - return false; // no B&O protocol + DEBUG_PRINT(F("B&O: Leading gap of ")); + DEBUG_PRINT((uint32_t)decodedIRData.initialGapTicks * 50); + DEBUG_PRINTLN(F(" us is wrong")); + return false; } - if (matchMark(irparams.rawbuf[1], BEO_BIT_MARK_FOR_DECODE)) { + if (matchMarkWithGreaterRange(irparams.rawbuf[1], BEO_BIT_MARK_FOR_DECODE)) { # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) protocolMarkLength = BEO_BIT_MARK_FOR_DECODE; } else if (matchMark(irparams.rawbuf[1], BEO_DATALINK_BIT_MARK)) { protocolMarkLength = BEO_DATALINK_BIT_MARK; # endif } else { - TRACE_PRINTLN(F("B&O: mark length is wrong")); + DEBUG_PRINTLN(F("B&O: mark length is wrong")); return false; } @@ -377,7 +405,7 @@ bool IRrecv::decodeBangOlufsen() { } } else { if (tPulseNumber == 3) { - if (matchMark(markLength, BEO_BIT_MARK_FOR_DECODE)) { + if (matchMarkWithGreaterRange(markLength, BEO_BIT_MARK_FOR_DECODE)) { # if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) protocolMarkLength = BEO_BIT_MARK_FOR_DECODE; } else if (matchMark(markLength, BEO_DATALINK_BIT_MARK)) { @@ -405,7 +433,7 @@ bool IRrecv::decodeBangOlufsen() { #if defined(SUPPORT_BEO_DATALINK_TIMING_FOR_DECODE) if (!matchMark(markLength, protocolMarkLength)) { #else - if (!matchMark(markLength, BEO_BIT_MARK_FOR_DECODE)) { + if (!matchMarkWithGreaterRange(markLength, BEO_BIT_MARK_FOR_DECODE)) { #endif DEBUG_PRINTLN(F("B&O: Mark length is wrong")); return false; diff --git a/src/ir_DistanceWidthProtocol.hpp b/src/ir_DistanceWidthProtocol.hpp index a86eef1b7..4313b320b 100644 --- a/src/ir_DistanceWidthProtocol.hpp +++ b/src/ir_DistanceWidthProtocol.hpp @@ -38,7 +38,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2022-2025 Armin Joachimsmeyer + * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/ir_JVC.hpp b/src/ir_JVC.hpp index d5276d2af..332c502b9 100644 --- a/src/ir_JVC.hpp +++ b/src/ir_JVC.hpp @@ -59,7 +59,6 @@ // 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. - #define JVC_ADDRESS_BITS 8 // 8 bit address #define JVC_COMMAND_BITS 8 // Command @@ -119,7 +118,7 @@ bool IRrecv::decodeJVC() { // Check we have the right amount of data (36 or 34). The +4 is for initial gap, start bit mark and space + stop bit mark. // +4 is for first frame, +2 is for repeats - if (decodedIRData.rawlen != ((2 * JVC_BITS) + 2) && decodedIRData.rawlen != ((2 * JVC_BITS) + 4)) { + if (!(decodedIRData.rawlen == ((2 * JVC_BITS) + 2) || decodedIRData.rawlen == ((2 * JVC_BITS) + 4))) { DEBUG_PRINT(F("JVC: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); DEBUG_PRINTLN(F(" is not 34 or 36")); @@ -128,10 +127,10 @@ bool IRrecv::decodeJVC() { if (decodedIRData.rawlen == ((2 * JVC_BITS) + 2)) { /* - * Check for repeat - * Check leading space and first and last mark length + * 34 -> check for repeat distance and check leading space and first and last mark length */ - if (decodedIRData.initialGapTicks < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK)) + if (lastDecodedProtocol == JVC + && decodedIRData.initialGapTicks < ((JVC_REPEAT_DISTANCE + (JVC_REPEAT_DISTANCE / 4) / MICROS_PER_TICK)) && matchMark(irparams.rawbuf[1], JVC_BIT_MARK) && matchMark(irparams.rawbuf[decodedIRData.rawlen - 1], JVC_BIT_MARK)) { /* @@ -144,6 +143,7 @@ bool IRrecv::decodeJVC() { } } else { + // 36 -> check for new start frame if (!checkHeader_P(&JVCProtocolConstants)) { return false; } diff --git a/src/ir_LG.hpp b/src/ir_LG.hpp index 1c7c37237..b15af079b 100644 --- a/src/ir_LG.hpp +++ b/src/ir_LG.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2017-2025 Darryl Smith, Armin Joachimsmeyer + * Copyright (c) 2017-2026 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 @@ -58,25 +58,26 @@ Sum: 62400 */ -// LG originally added by Darryl Smith (based on the JVC protocol) -// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/LGAirConditionerSendDemo +// LG originally added by Darryl Smith +// see: https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/SendLGAirConditionerDemo // see: https://www.mikrocontroller.net/articles/IRMP_-_english#LGAIR // MSB first, 1 start bit + 8 bit address + 16 bit command + 4 bit checksum + 1 stop bit (28 data bits). -// Bit and repeat timing is like NEC -// LG2 has different header timing and a shorter bit time than LG +// +// LG is MSB first and has 28 bits in contrast to NEC, which is LSB first and has 32 bits. +// LG Bit and repeat timing is like NEC, but with 526 us instead of 560 us unit. /* * LG remote IR-LED measurements: Type AKB 73315611 for air conditioner, Ver1.1 from 2011.03.01 - * Protocol: LG2 + * Protocol: LG * Internal crystal: 4 MHz * Header: 8.9 ms mark 4.15 ms space - * Data: 500 / 540 and 500 / 1580; + * Data: 526 / 526 and 526 / 1578; * Clock is not synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark * Duty: 9 us on 17 us off => around 33 % duty * NO REPEAT: If value like temperature has changed during long press, the last value is send at button release. * If you do a double press, the next value can be sent after around 118 ms. Tested with the fan button. * LG remote IR-LED measurements: Type AKB 75095308 for LG TV - * Protocol: NEC!!! + * Protocol: !!!NEC!!! * Frequency 37.88 kHz * Header: 9.0 ms mark 4.5 ms space * Data: 560 / 560 and 560 / 1680; @@ -92,40 +93,34 @@ #define LG_CHECKSUM_BITS 4 #define LG_BITS (LG_ADDRESS_BITS + LG_COMMAND_BITS + LG_CHECKSUM_BITS) // 28 -#define LG_UNIT 500 // 19 periods of 38 kHz +#define LG_UNIT 526 // 20 periods of 38 kHz -#define LG_HEADER_MARK (18 * LG_UNIT) // 9000 -#define LG_HEADER_SPACE 4200 // 4200 | 84 - -#define LG2_HEADER_MARK (19 * LG_UNIT) // 9500 -#define LG2_HEADER_SPACE (6 * LG_UNIT) // 3000 +#define LG_HEADER_MARK (16 * LG_UNIT) // 8416 +#define LG_HEADER_SPACE (8 * LG_UNIT) // 4208 #define LG_BIT_MARK LG_UNIT -#define LG_ONE_SPACE 1580 // 60 periods of 38 kHz +#define LG_ONE_SPACE 1578 // 60 periods of 38 kHz #define LG_ZERO_SPACE 550 -#define LG_REPEAT_HEADER_SPACE (4 * LG_UNIT) // 2250 +#define LG_REPEAT_HEADER_SPACE (4 * LG_UNIT) // 2104 #define LG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down. //#define LG_AVERAGE_DURATION 58000 // LG_HEADER_MARK + LG_HEADER_SPACE + 32 * 2,5 * LG_UNIT) + LG_UNIT // 2.5 because we assume more zeros than ones //#define LG_REPEAT_DURATION (LG_HEADER_MARK + LG_REPEAT_HEADER_SPACE + LG_BIT_MARK) //#define LG_REPEAT_DISTANCE (LG_REPEAT_PERIOD - LG_AVERAGE_DURATION) // 52 ms 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 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}; + LG_ONE_SPACE, LG_BIT_MARK, LG_ZERO_SPACE, PROTOCOL_IS_MSB_FIRST | PROTOCOL_IS_PULSE_DISTANCE, (LG_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), &sendLGSpecialRepeat}; /************************************ * Start of send and decode functions ************************************/ /* - * Send special LG2 repeat - not used internally + * Send special LG repeat. Like NEC repeat, but with unit 526 instead of 560 - not used internally */ -void IRsend::sendLG2Repeat() { - enableIROut (LG_KHZ); // 38 kHz - mark(LG2_HEADER_MARK); // + 3000 - space(LG_REPEAT_HEADER_SPACE); // - 2250 +void IRsend::sendLGRepeat() { + enableIROut (LG_KHZ); // 38 kHz + mark(LG_HEADER_MARK); // + 8416 + space(LG_REPEAT_HEADER_SPACE); // - 2104 mark(LG_BIT_MARK); // + 500 } @@ -133,11 +128,11 @@ void IRsend::sendLG2Repeat() { * Static function for sending special repeat frame. * For use in ProtocolConstants. Saves up to 250 bytes compared to a member function. */ -void sendLG2SpecialRepeat() { - IrSender.enableIROut(LG_KHZ); // 38 kHz - IrSender.mark(LG2_HEADER_MARK); // + 3000 - IrSender.space(LG_REPEAT_HEADER_SPACE); // - 2250 - IrSender.mark(LG_BIT_MARK); // + 500 +void sendLGSpecialRepeat() { + IrSender.enableIROut(LG_KHZ); // 38 kHz + IrSender.mark(LG_HEADER_MARK); // + 8416 + IrSender.space(LG_REPEAT_HEADER_SPACE); // - 2104 + IrSender.mark(LG_BIT_MARK); // + 500 } uint32_t IRsend::computeLGRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand) { @@ -155,22 +150,14 @@ uint32_t IRsend::computeLGRawDataAndChecksum(uint8_t aAddress, uint16_t aCommand return (tRawData | (tChecksum & 0xF)); } -/** - * LG uses the NEC repeat. - */ void IRsend::sendLG(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { sendPulseDistanceWidth_P(&LGProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats); } -/** - * LG2 uses a special repeat. +/* + * Decode MSB first and 28 bits */ -void IRsend::sendLG2(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats) { - sendPulseDistanceWidth_P(&LG2ProtocolConstants, computeLGRawDataAndChecksum(aAddress, aCommand), LG_BITS, aNumberOfRepeats); -} - bool IRrecv::decodeLG() { - decode_type_t tProtocol = LG; uint16_t tHeaderSpace = LG_HEADER_SPACE; /* @@ -180,7 +167,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)) { + if (!(decodedIRData.rawlen == ((2 * LG_BITS) + 4) || (decodedIRData.rawlen == 4))) { // Is only printed, if LOCAL_DEBUG is defined globally DEBUG_PRINT(F("LG: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); @@ -190,22 +177,18 @@ bool IRrecv::decodeLG() { // Check header "mark" this must be done for repeat and data if (!matchMark(irparams.rawbuf[1], LG_HEADER_MARK)) { - if (matchMark(irparams.rawbuf[1], LG2_HEADER_MARK)) { - tProtocol = LG2; - tHeaderSpace = LG2_HEADER_SPACE; - } else { - DEBUG_PRINTLN(F("LG: Header mark is wrong")); - return false; // neither LG nor LG2 header - } + DEBUG_PRINTLN(F("LG: Header mark is wrong")); + return false; } // Check for repeat - here we have another header space length if (decodedIRData.rawlen == 4) { - if (matchSpace(irparams.rawbuf[2], LG_REPEAT_HEADER_SPACE) && matchMark(irparams.rawbuf[3], LG_BIT_MARK)) { + if (lastDecodedProtocol == LG && 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; - decodedIRData.protocol = lastDecodedProtocol; + decodedIRData.protocol = LG; return true; } DEBUG_PRINTLN(F("LG: Repeat header space is wrong")); @@ -247,7 +230,7 @@ bool IRrecv::decodeLG() { decodedIRData.flags |= IRDATA_FLAGS_PARITY_FAILED; } - decodedIRData.protocol = tProtocol; // LG or LG2 + decodedIRData.protocol = LG; decodedIRData.numberOfBits = LG_BITS; return true; diff --git a/src/ir_Lego.hpp b/src/ir_Lego.hpp index 506f174eb..574921a01 100644 --- a/src/ir_Lego.hpp +++ b/src/ir_Lego.hpp @@ -147,7 +147,8 @@ bool IRrecv::decodeLegoPowerFunctions() { * 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))) { + if (!(matchMarkWithGreaterRange(irparams.rawbuf[1], LEGO_HEADER_MARK) && (matchSpace(irparams.rawbuf[2], LEGO_HEADER_SPACE)))) { + DEBUG_PRINTLN(F("LEGO: No header mark and space")); return false; } diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 54aff4880..60ea75988 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -95,14 +95,14 @@ #define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS) #define NEC_UNIT 560 // 21.28 periods of 38 kHz, 11.2 ticks TICKS_LOW = 8.358 TICKS_HIGH = 15.0 -#define NEC_HEADER_MARK (16 * NEC_UNIT) // 9000 | 180 -#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4500 | 90 +#define NEC_HEADER_MARK (16 * NEC_UNIT) // 8960 | 180 +#define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4480 | 90 #define NEC_BIT_MARK NEC_UNIT #define NEC_ONE_SPACE (3 * NEC_UNIT) // 1690 | 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0 #define NEC_ZERO_SPACE NEC_UNIT -#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2250 +#define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2240 #define NEC_AVERAGE_DURATION 62000 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2,5 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones #define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones @@ -239,7 +239,7 @@ bool IRrecv::decodeNEC() { * Next try the decode */ // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawlen != ((2 * NEC_BITS) + 4) && (decodedIRData.rawlen != 4)) { + if (!(decodedIRData.rawlen == ((2 * NEC_BITS) + 4) || (decodedIRData.rawlen == 4))) { DEBUG_PRINT(F("NEC: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); DEBUG_PRINTLN(F(" is not 68 or 4")); @@ -258,7 +258,7 @@ bool IRrecv::decodeNEC() { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; decodedIRData.command = lastDecodedCommand; - decodedIRData.protocol = lastDecodedProtocol; + decodedIRData.protocol = lastDecodedProtocol; // Allow recognition of repeats of NEC, APPLE, ONKYO and OPENLASIR and maybe LG return true; } return false; diff --git a/src/ir_OpenLASIR.hpp b/src/ir_OpenLASIR.hpp index 945452248..acb3a77f2 100644 --- a/src/ir_OpenLASIR.hpp +++ b/src/ir_OpenLASIR.hpp @@ -234,7 +234,7 @@ bool IRrecv::decodeOpenLASIR() { */ // Check we have the right amount of data (68). The +4 is for initial gap, start bit mark and space + stop bit mark. - if (decodedIRData.rawlen != ((2 * OPENLASIR_BITS) + 4) && (decodedIRData.rawlen != 4)) { + if (!(decodedIRData.rawlen == ((2 * OPENLASIR_BITS) + 4) || (decodedIRData.rawlen == 4))) { DEBUG_PRINT(F("OpenLASIR: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); DEBUG_PRINTLN(F(" is not 68 or 4")); @@ -246,19 +246,19 @@ bool IRrecv::decodeOpenLASIR() { return false; } +#if !defined(DECODE_NEC) // This code is also contained in NEC sources and does also decode LASIR Repeats :-) // Check for repeat - here we have another header space length if (decodedIRData.rawlen == 4) { - // Only claim this repeat if the last decoded protocol was OpenLASIR - if (lastDecodedProtocol == OPENLASIR && matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) - && matchMark(irparams.rawbuf[3], NEC_BIT_MARK)) { + if (matchSpace(irparams.rawbuf[2], NEC_REPEAT_HEADER_SPACE) && matchMark(irparams.rawbuf[3], NEC_BIT_MARK)) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; decodedIRData.command = lastDecodedCommand; - decodedIRData.protocol = OPENLASIR; + decodedIRData.protocol = lastDecodedProtocol; // Allow recognition of repeats of another look alike protocol return true; } return false; } +#endif // Check command header space if (!matchSpace(irparams.rawbuf[2], NEC_HEADER_SPACE)) { diff --git a/src/ir_RC5_RC6.hpp b/src/ir_RC5_RC6.hpp index 5c5c7a23d..b988011bf 100644 --- a/src/ir_RC5_RC6.hpp +++ b/src/ir_RC5_RC6.hpp @@ -65,6 +65,26 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only +1850 Duration=23250us + RC5 minimal length (RX5X) + Protocol=RC5 Address=0xA, Command=0x6A, Toggle=1, Raw-Data=0xAAA, 13 bits, MSB first + rawIRTimings[14]: + -746950 + +1900,-1700 + +1850,-1700 +1800,-1750 +1800,-1750 +1800,-1750 + +1800,-1750 +1750 + Duration=23100us + + RC5 maximal length + Protocol=RC5 Address=0x1F, Command=0x3F, Toggle=1, Raw-Data=0x1FFF, 13 bits, MSB first + rawIRTimings[28]: + -391800 + + 950,- 850 + + 950,- 800 + 950,- 850 + 900,- 900 + 950,- 800 + + 950,- 850 + 900,- 900 + 900,- 850 +1000,- 800 + +1000,- 800 + 850,- 950 + 950,- 800 +1000,- 800 + + 900 + Duration=24100us + Protocol=Marantz Address=0x11, Command=0x76, Extra=0x9, Toggle=1, Raw-Data=0x31D89, 19 bits, MSB first +1850,-1700 + 950,- 850 +1850,- 850 + 950,- 800 +1000,-1700 @@ -72,6 +92,18 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only +1850,- 850 + 950,- 800 +1000,-1700 +1800,- 900 + 900,-1750 + 950 Duration=38400us + +Marantz maximal length +Protocol=Marantz Address=0x1F, Command=0x3F, Extra=0x3F, Toggle=1, Raw-Data=0x7FFFF, 19 bits, MSB first +rawIRTimings[40]: + -398900 + + 950,- 850 + + 850,- 950 + 900,- 900 + 950,- 850 + 950,- 800 + +1000,- 800 + 900,- 900 + 950,-4350 + 950,- 850 + + 950,- 800 +1000,- 800 + 850,- 950 + 950,- 850 + + 900,- 850 + 950,- 850 + 950,- 850 + 950,- 800 + +1000,- 800 + 950,- 850 + 850 +Duration=38350us */ // // see: https://www.sbprojects.net/knowledge/ir/rc5.php @@ -120,10 +152,11 @@ uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0. Only /* * Just in case to permanently send it as 0 because start value is 1, * or to reset toggle bit after a transmission with automatic toggling. + * Sets sLastSendToggleValue to inverse in order to get aRC5ToggleBitValue as next sent toggle value because it is inverted before each sending! * @param aRC5ToggleBitValue 0 or 1, only LSB is taken */ -void IRsend::setToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue) { - sLastSendToggleValue = aRC5ToggleBitValue & 0x01; +void IRsend::setNextToggleBitValueForRC5AndRC6(uint8_t aRC5ToggleBitValue) { + sLastSendToggleValue = (aRC5ToggleBitValue & 0x01) ^ 0x01; } /** @@ -260,12 +293,11 @@ uint8_t IRrecv::getNumberOfUnitsInInterval(uint16_t aCurrentInterval, uint16_t a * _ _ _ _ _ _ _ _ _ _ _ _ _ * _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period + * | | | | | | | | | | | | | | Bit period * _ _ _ ___ _ ___ ___ _ - Mark * Data _____| |___| |_| |_| |_| |___| |___| |_| | - Data starts with a mark->space bit * 1 0 0 0 1 1 0 1 0 1 1 - Space - * A mark to space at a significant clock edge results in a 1 - * A space to mark at a significant clock edge results in a 0 + * * Returns current level [MARK or SPACE] or NO_MARK_OR_SPACE for error (measured time interval is not a multiple of BiphaseTimeUnit). */ uint_fast8_t IRrecv::getBiphaselevel() { @@ -316,18 +348,18 @@ uint_fast8_t IRrecv::getBiphaselevel() { #if defined(DECODE_RC5) || defined(DECODE_MARANTZ) /** * Try to decode data as RC5 protocol - * mark->space => 0 + * mark->space => 0 - Inverse of RC6! * space->mark => 1 * _ _ _ _ _ _ _ _ _ _ _ _ _ * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value + * | | | | | | | | | | | | | Bit period * _ _ * 2 Start bits for RC5 _____| |_| ..|...|.. - * - * _ - * 1 Start bit for RC5X _____| ..|...|...|.. - * + * S S T Address + * ___ + * 1 Start bit for RC5X _____| |_..|...|.. + * S 0 T Address */ bool IRrecv::decodeRC5() { uint8_t tBitIndex; @@ -336,12 +368,22 @@ bool IRrecv::decodeRC5() { // Set Biphase decoding start values initBiphaselevel(1, RC5_UNIT); // Skip gap space - // Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark. - if (decodedIRData.rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawlen) { + // Check we have the right amount of data (14 to 26). The +1 is for initial gap. +2 for initial gap and mark of last bit which is a 1 + if (decodedIRData.rawlen < (RC5_BITS + 1) /* 14 */ || +#if defined(DECODE_MARANTZ) + ((MARANTZ_BITS * 2) + 2) /* 40, the pause is just extended */ < decodedIRData.rawlen +#else + ((RC5_BITS * 2) + 2) /* 28 */ < decodedIRData.rawlen +#endif + ) { // no debug output, since this check is mainly to determine the received protocol DEBUG_PRINT(F("RC5: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); - DEBUG_PRINTLN(F(" is not between 9 and 15")); +#if defined(DECODE_MARANTZ) + DEBUG_PRINTLN(F(" is not between 14 and 40")); +#else + DEBUG_PRINTLN(F(" is not between 14 and 28")); +#endif return false; } @@ -487,6 +529,32 @@ bool IRrecv::decodeRC5() { + 550,- 400 +1000,- 800 +1000,- 400 + 500,- 400 + 500,- 900 +1000,- 350 + 550,- 850 + 500 Duration=37450us + + RC6 minimal length + Protocol=RC6 Address=0x55, Command=0x55, Toggle=1, Raw-Data=0x15555, 20 bits, MSB first + rawIRTimings[26]: + -397700 + +2700,- 800 + + 550,- 850 + 450,- 450 + 500,- 400 +1400,-1300 + + 950,- 850 + 900,- 900 +1000,- 850 + 950,- 850 + +1000,- 850 + 950,- 850 + 900,- 900 +1000 + Duration=23100us + + RC6A maximal length + Protocol=RC6A Address=0xFF, Command=0xFF, Extra=0x3FFF, Raw-Data=0x7FFFFFFF, 35 bits, MSB first + rawIRTimings[72]: + -399750 + +2700,- 850 + + 500,- 400 + 550,- 400 + 400,- 900 + 500,- 850 + +1450,- 400 + 500,- 400 + 550,- 400 + 400,- 500 + + 500,- 400 + 550,- 350 + 550,- 400 + 400,- 500 + + 450,- 450 + 500,- 400 + 500,- 400 + 550,- 400 + + 400,- 500 + 450,- 450 + 550,- 350 + 500,- 450 + + 400,- 500 + 450,- 450 + 550,- 350 + 500,- 450 + + 400,- 500 + 450,- 450 + 550,- 350 + 550,- 400 + + 400,- 500 + 450,- 450 + 550,- 350 + 550,- 400 + + 450,- 450 + 450,- 450 + 450 + Duration=36800us */ // Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit and constant bit 1 // Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits + 2666us pause - 37 bits incl. start bit @@ -500,16 +568,19 @@ bool IRrecv::decodeRC5() { #define RC6_RPT_LENGTH 46000 -#define RC6_LEADING_BIT 1 -#define RC6_MODE_BITS 3 // never seen others than all 0 for Philips TV -#define RC6_TOGGLE_BIT 1 // toggles at every key press. Can be used to distinguish repeats from 2 key presses and has another timing :-(. +#define RC6_LEADING_BIT_ONE 1 +#define RC6_MODE_BITS 3 // Never seen others than all 0 for Philips TV :-) +#define RC6_TOGGLE_BIT 1 // Toggles at every key press. Can be used to distinguish repeats from 2 key presses and has another timing :-(. #define RC6_TOGGLE_BIT_INDEX RC6_MODE_BITS // fourth position, index = 3 #define RC6_ADDRESS_BITS 8 #define RC6_COMMAND_BITS 8 -#define RC6_CUSTOMER_BITS 14 +#define RC6A_CUSTOMER_BIT_ONE 1 +#define RC6A_CUSTOMER_BITS 14 -#define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 21 -#define RC6A_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + 1 + RC6_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 36 +#define RC6_BITS (RC6_LEADING_BIT_ONE + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 21 +#define RC6A_BITS (RC6_LEADING_BIT_ONE + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6A_CUSTOMER_BIT_ONE + RC6A_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 36 +#define RC6A_FIXED_BITS (RC6_LEADING_BIT_ONE + RC6_MODE_BITS) // 4 +#define RC6A_VARIABLE_BITS (RC6_TOGGLE_BIT + RC6A_CUSTOMER_BIT_ONE + RC6A_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // Without fixed protocol specific bits 33 #define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444) @@ -517,7 +588,7 @@ bool IRrecv::decodeRC5() { #define RC6_HEADER_SPACE (2 * RC6_UNIT) // 889 #define RC6_TRAILING_SPACE (6 * RC6_UNIT) // 2666 -#define MIN_RC6_MARKS 4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2) // 12, 4 are for preamble +#define MIN_RC6_MARKS (4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2)) // 12, 4 are for preamble #define RC6_REPEAT_DISTANCE 107000 // just a guess but > 2.666ms #define RC6_MAXIMUM_REPEAT_DISTANCE (RC6_REPEAT_DISTANCE + (RC6_REPEAT_DISTANCE / 4)) // Just a guess @@ -570,15 +641,15 @@ void IRsend::sendRC6Raw(uint64_t aRawData, uint8_t aNumberOfBitsToSend) { mark(RC6_HEADER_MARK); space(RC6_HEADER_SPACE); -// Start bit +// Leading bit 1 mark(RC6_UNIT); space(RC6_UNIT); // Data MSB first uint64_t mask = 1ULL << (aNumberOfBitsToSend - 1); - for (uint_fast8_t i = 1; mask; i++, mask >>= 1) { + for (uint_fast8_t i = 0; mask; i++, mask >>= 1) { // The fourth bit we send is the "double width toggle bit" - unsigned int t = (i == (RC6_TOGGLE_BIT_INDEX + 1)) ? (RC6_UNIT * 2) : (RC6_UNIT); + unsigned int t = (i == RC6_TOGGLE_BIT_INDEX) ? (RC6_UNIT * 2) : (RC6_UNIT); if (aRawData & mask) { mark(t); space(t); @@ -643,7 +714,7 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR tIRRawData.UByte.LowByte = aCommand; tIRRawData.UByte.MidLowByte = aAddress; - tIRRawData.UWord.HighWord = aCustomer | 0x400; // bit 31 is always 1 + tIRRawData.UWord.HighWord = aCustomer | 0x4000; // bit 31 is always 1 if (aEnableAutomaticToggle) { // invert toggle bit if enabled @@ -666,7 +737,7 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR while (tNumberOfCommands > 0) { // start and leading bits are sent by sendRC6 - sendRC6Raw(tRawData, RC6A_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6 + sendRC6Raw(tRawData, RC6A_BITS - 1); // -1 since the leading bit 1 is sent by sendRC6Raw() tNumberOfCommands--; // skip last delay! @@ -683,26 +754,28 @@ void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfR * Unit is 444 us and half of RC5 unit 888 * mark->space => 1 - Inverse of RC5! * space->mark => 0 - * _ _ _ _ _ _ _ _ _ _ _ _ _ - * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | 444 us high and low - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ End of clock / each data bit period - * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value - * ______ _ _ _ _ - * Start bit for RC6 _____| |_| |___| |_| |_| ......|.......|.. - * Start 1 0 0 0 ^double timing toggle bit + 8 bit address + 8 bit command - * ______ _ _ _ _ _ - * Start bit for RC6A _____| |_| |_| |_| |___| ......|...... |_.. - * Start 1 1 1 0 toggle^ bit 1 + 14 bit extra + 8 bit address + 8 bit command + * _ _ _ _ _ _ _ _ _ _ _ _ _ + * Clock _____| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| |_| | 444 us high and low + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ Significant clock edge /sample point for bit value + * | | | | | | | | | Bit period + * ______ _ _ _ _ + * Start bit for RC6 _____| |__| |___| |_| |_| ......|.......|.. + * Start 1 0 0 0 ^double timing toggle bit + 8 bit address + 8 bit command + * ______ _ _ _ _ _ + * Start bit for RC6A _____| |__| |_| |_| |___| ......|...... |_.. + * Start 1 1 1 0 ^ 1 + 14 bit extra + 8 bit address + 8 bit command + * ^ toggle bit ^ + * Fixed 1 for RC6 Fixed 1 for RC6A */ bool IRrecv::decodeRC6() { uint8_t tBitIndex; uint32_t tDecodedRawData = 0; - // Check we have the right amount of data (). The +3 for initial gap, start bit mark and space - if (decodedIRData.rawlen < MIN_RC6_MARKS + 3 && (RC6_BITS + 3) < decodedIRData.rawlen) { + // Check we have the right amount of data (). The +3 for initial gap, start bit mark and space. +6 for timing of fixed 1 and mode + if (decodedIRData.rawlen < 26 || 72 < decodedIRData.rawlen) { DEBUG_PRINT(F("RC6: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); - DEBUG_PRINTLN(F(" is not between 15 and 25")); + DEBUG_PRINTLN(F(" is not between 26 and 72")); return false; } @@ -714,19 +787,21 @@ bool IRrecv::decodeRC6() { } // Set Biphase decoding start values - initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark + space + initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark and space - // Check first bit, which is known to be a 1 (mark->space) + /* + * Check first bit, which is known to be a 1 (mark->space) + */ if (getBiphaselevel() != MARK) { DEBUG_PRINTLN(F("RC6: first getBiphaselevel() is not MARK")); return false; } - // Check second bit if (getBiphaselevel() != SPACE) { DEBUG_PRINTLN(F("RC6: second getBiphaselevel() is not SPACE")); return false; } + // Now start decoding at bit 2 / mode bits for (tBitIndex = 0; irparams.RawbuffOffsetForNextBiphaseLevel < decodedIRData.rawlen; tBitIndex++) { uint8_t tStartLevel; // start level of coded bit uint8_t tEndLevel; // end level of coded bit @@ -753,11 +828,11 @@ bool IRrecv::decodeRC6() { * Determine tDecodedRawData bit value by checking the transition type */ if ((tStartLevel == MARK) && (tEndLevel == SPACE)) { - // we have a mark to space transition here - tDecodedRawData = (tDecodedRawData << 1) | 1; // inverted compared to RC5 + // we have a mark to space transition here -> 1 + tDecodedRawData = (tDecodedRawData << 1) | 1; // inverted value compared to RC5 } else if ((tStartLevel == SPACE) && (tEndLevel == MARK)) { - // we have a space to mark transition here - tDecodedRawData = (tDecodedRawData << 1) | 0; + // we have a space to mark transition here -> 0 + tDecodedRawData = (tDecodedRawData << 1); } else { DEBUG_PRINTLN(F("RC6: Decode failed")); // we have no transition here or one level is -1 -> error diff --git a/src/ir_Samsung.hpp b/src/ir_Samsung.hpp index 462ca4846..d9a1b9186 100644 --- a/src/ir_Samsung.hpp +++ b/src/ir_Samsung.hpp @@ -8,7 +8,7 @@ ************************************************************************************ * MIT License * - * Copyright (c) 2017-2025 Darryl Smith, Armin Joachimsmeyer + * Copyright (c) 2017-2026 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 @@ -93,7 +93,7 @@ #define SAMSUNG_ONE_SPACE (3 * SAMSUNG_UNIT) // 1690 | 33.8 TICKS_LOW = 25.07 TICKS_HIGH = 45.0 #define SAMSUNG_ZERO_SPACE SAMSUNG_UNIT -#define SAMSUNG_AVERAGE_DURATION 55000 // SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones +#define SAMSUNG_AVERAGE_DURATION 55000 // Not used. SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + 32 * 2,5 * SAMSUNG_UNIT + SAMSUNG_UNIT // 2.5 because we assume more zeros than ones #define SAMSUNG_REPEAT_DURATION (SAMSUNG_HEADER_MARK + SAMSUNG_HEADER_SPACE + SAMSUNG_BIT_MARK + SAMSUNG_ZERO_SPACE + SAMSUNG_BIT_MARK) #define SAMSUNG_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down. #define SAMSUNG_MAXIMUM_REPEAT_DISTANCE (SAMSUNG_REPEAT_PERIOD + (SAMSUNG_REPEAT_PERIOD / 4)) // 137000 - Just a guess @@ -270,8 +270,8 @@ void IRsend::sendSamsung48(uint16_t aAddress, uint32_t aCommand, int_fast8_t aNu bool IRrecv::decodeSamsung() { // Check we have enough data (68). The +4 is for initial gap, start bit mark and space + stop bit mark - if (decodedIRData.rawlen != ((2 * SAMSUNG_BITS) + 4) && decodedIRData.rawlen != ((2 * SAMSUNG48_BITS) + 4) - && (decodedIRData.rawlen != 6)) { + if (!(decodedIRData.rawlen == ((2 * SAMSUNG_BITS) + 4) || decodedIRData.rawlen == ((2 * SAMSUNG48_BITS) + 4) + || (decodedIRData.rawlen == 6))) { DEBUG_PRINT(F("Samsung: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); DEBUG_PRINTLN(F(" is not 6 or 68 or 100")); @@ -283,7 +283,7 @@ bool IRrecv::decodeSamsung() { } // Check for SansungLG style repeat - if (decodedIRData.rawlen == 6) { + if (lastDecodedProtocol == SAMSUNGLG && decodedIRData.rawlen == 6) { decodedIRData.flags = IRDATA_FLAGS_IS_REPEAT | IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT | IRDATA_FLAGS_IS_LSB_FIRST; decodedIRData.address = lastDecodedAddress; decodedIRData.command = lastDecodedCommand; diff --git a/src/ir_Sony.hpp b/src/ir_Sony.hpp index 72c136852..0d76da346 100644 --- a/src/ir_Sony.hpp +++ b/src/ir_Sony.hpp @@ -83,10 +83,10 @@ #define SONY_ZERO_MARK SONY_UNIT #define SONY_SPACE SONY_UNIT -#define SONY_AVERAGE_DURATION_MIN 21000 // SONY_HEADER_MARK + SONY_SPACE + 12 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones -#define SONY_AVERAGE_DURATION_MAX 33000 // SONY_HEADER_MARK + SONY_SPACE + 20 * 2,5 * SONY_UNIT // 2.5 because we assume more zeros than ones -#define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down. -#define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_AVERAGE_DURATION_MIN) // 24 ms +#define SONY_DURATION_MIN 17400 // SONY_HEADER_MARK + SONY_SPACE + 12 * 2 * SONY_UNIT = 29 * SONY_UNIT +#define SONY_DURATION_MAX 37200 // SONY_HEADER_MARK + SONY_SPACE + 20 * 3 * SONY_UNIT = 65 * SONY_UNIT +#define SONY_REPEAT_PERIOD 45000 // Commands are repeated every 45 ms (measured from start to start) for as long as the key on the remote control is held down. +#define SONY_MAXIMUM_REPEAT_DISTANCE (SONY_REPEAT_PERIOD - SONY_DURATION_MIN) // 27,6 ms struct PulseDistanceWidthProtocolConstants const SonyProtocolConstants PROGMEM = { SONY, SONY_KHZ, SONY_HEADER_MARK, SONY_SPACE, SONY_ONE_MARK, SONY_SPACE, SONY_ZERO_MARK, SONY_SPACE, PROTOCOL_IS_LSB_FIRST | PROTOCOL_IS_PULSE_WIDTH, (SONY_REPEAT_PERIOD / MICROS_IN_ONE_MILLI), nullptr }; @@ -111,8 +111,8 @@ bool IRrecv::decodeSony() { } // Check we have enough data. +2 for initial gap and start bit mark and space minus the last/MSB space. NO stop bit! 26, 32, 42 - if (decodedIRData.rawlen != (2 * SONY_BITS_MIN) + 2 && decodedIRData.rawlen != (2 * SONY_BITS_MAX) + 2 - && decodedIRData.rawlen != (2 * SONY_BITS_15) + 2) { + if (!(decodedIRData.rawlen == (2 * SONY_BITS_MIN) + 2 || decodedIRData.rawlen == (2 * SONY_BITS_MAX) + 2 + || decodedIRData.rawlen == (2 * SONY_BITS_15) + 2)) { DEBUG_PRINT(F("Sony: Data length=")); DEBUG_PRINT(decodedIRData.rawlen); DEBUG_PRINTLN(F(" is not 12, 15 or 20")); diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 4358904be..b0b224919 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -39,6 +39,7 @@ * 8 MHZ F_CPU and 38 kHz -> no prescaling , divider = 210.526 -> 38.1 kHz with divider 210 * 4 MHZ F_CPU and 38 kHz -> no prescaling , divider = 105.26 -> 38.1 kHz with divider 105 * 1 MHZ F_CPU and 38 kHz -> no prescaling , divider = 26.31 -> 38.4 kHz with divider 36 + * 38 kHz = 26.3157 us */ #ifndef _IR_TIMER_HPP #define _IR_TIMER_HPP From 64d3073084957a85d7c2e56542297355c46a4af1 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sat, 28 Mar 2026 11:50:41 +0100 Subject: [PATCH 127/133] Handling of DECODE_PANASONIC --- README.md | 2 +- changelog.md | 2 +- examples/CallbackDemo/CallbackDemo.ino | 3 +- examples/IRremoteInfo/IRremoteInfo.ino | 7 -- .../MultipleReceivers/MultipleReceivers.ino | 3 +- examples/ReceiveAndSend/ReceiveAndSend.ino | 3 +- examples/ReceiveDemo/ReceiveDemo.ino | 97 +++++++++++-------- examples/SimpleReceiver/SimpleReceiver.ino | 61 +++++++----- examples/UnitTest/UnitTest.ino | 33 +++---- src/IRFeedbackLED.hpp | 2 +- src/IRProtocol.h | 43 ++++---- src/IRReceive.hpp | 7 +- src/ir_NEC.hpp | 2 +- src/private/IRTimer.hpp | 3 +- 14 files changed, 143 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 70f0fbaa2..91c36ff2e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A library enabling the sending & receiving of infrared signals. [![Badge License: MIT](https://img.shields.io/badge/License-MIT-ac8b11.svg?style=for-the-badge&labelColor=yellow)](https://opensource.org/licenses/MIT)     -[![Badge Version](https://img.shields.io/github/v/release/Arduino-IRremote/Arduino-IRremote?include_prereleases&style=for-the-badge&color=33660e&labelColor=428813&logoColor=white&logo=DocuSign)](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest) +[![Badge Version](https://img.shields.io/github/v/release/Arduino-IRremote/Arduino-IRremote?style=for-the-badge&color=33660e&labelColor=428813&logoColor=white&logo=DocuSign)](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/latest)     [![Badge Commits since latest](https://img.shields.io/github/commits-since/Arduino-IRremote/Arduino-IRremote/latest?style=for-the-badge&color=004463&labelColor=00557f)](https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master)     diff --git a/changelog.md b/changelog.md index cfce902b8..1a4a549f9 100644 --- a/changelog.md +++ b/changelog.md @@ -2,7 +2,7 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master -# 4.6.2 +# 4.7.0 - Added removed typedef `IRRawDataType` for backward compatibility. - Modified and renamed function `setToggleBitValueForRC5AndRC6()` to `setNextToggleBitValueForRC5AndRC6()`. - Fixed bug in sending RC6A. diff --git a/examples/CallbackDemo/CallbackDemo.ino b/examples/CallbackDemo/CallbackDemo.ino index bd348d14e..05342d827 100644 --- a/examples/CallbackDemo/CallbackDemo.ino +++ b/examples/CallbackDemo/CallbackDemo.ino @@ -38,8 +38,7 @@ */ //#define DECODE_DENON // Includes Sharp //#define DECODE_JVC -//#define DECODE_KASEIKYO -//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO +//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes //#define DECODE_LG #define DECODE_NEC // Includes Apple and Onkyo //#define DECODE_SAMSUNG diff --git a/examples/IRremoteInfo/IRremoteInfo.ino b/examples/IRremoteInfo/IRremoteInfo.ino index 4aa3c603d..7f8ef9e32 100644 --- a/examples/IRremoteInfo/IRremoteInfo.ino +++ b/examples/IRremoteInfo/IRremoteInfo.ino @@ -269,13 +269,6 @@ void dumpProtocols() { Serial.println(F("Disabled")); #endif - Serial.print(F("PANASONIC: ")); -#if defined(DECODE_PANASONIC) - Serial.println(F("Enabled")); -#else - Serial.println(F("Disabled")); -#endif - Serial.print(F("JVC: ")); #if defined(DECODE_JVC) Serial.println(F("Enabled")); diff --git a/examples/MultipleReceivers/MultipleReceivers.ino b/examples/MultipleReceivers/MultipleReceivers.ino index d1cc9e1d1..c60b990c3 100644 --- a/examples/MultipleReceivers/MultipleReceivers.ino +++ b/examples/MultipleReceivers/MultipleReceivers.ino @@ -41,8 +41,7 @@ */ //#define DECODE_DENON // Includes Sharp //#define DECODE_JVC -//#define DECODE_KASEIKYO -//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO +//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes //#define DECODE_LG //#define DECODE_NEC // Includes Apple and Onkyo. To enable all protocols , just comment/disable this line. //#define DECODE_SAMSUNG diff --git a/examples/ReceiveAndSend/ReceiveAndSend.ino b/examples/ReceiveAndSend/ReceiveAndSend.ino index 7b2715263..faae9a06e 100644 --- a/examples/ReceiveAndSend/ReceiveAndSend.ino +++ b/examples/ReceiveAndSend/ReceiveAndSend.ino @@ -53,8 +53,7 @@ */ //#define DECODE_DENON // Includes Sharp //#define DECODE_JVC -//#define DECODE_KASEIKYO -//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO +//#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes //#define DECODE_LG //#define DECODE_NEC // Includes Apple and Onkyo //#define DECODE_SAMSUNG diff --git a/examples/ReceiveDemo/ReceiveDemo.ino b/examples/ReceiveDemo/ReceiveDemo.ino index 2cd0eedc5..6de9fb7f0 100644 --- a/examples/ReceiveDemo/ReceiveDemo.ino +++ b/examples/ReceiveDemo/ReceiveDemo.ino @@ -40,56 +40,66 @@ /* * Specify which protocol(s) should be used for decoding. - * If no protocol is defined, all protocols (except Bang&Olufsen) are active. + * If no protocol is defined, all protocols (except BEO / Bang&Olufsen) are active. * This must be done before the #include + * In alphabetic order */ -//#define DECODE_DENON // Includes Sharp -//#define DECODE_JVC -//#define DECODE_KASEIKYO -//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO -//#define DECODE_LG -//#define DECODE_NEC // Includes Apple and Onkyo -//#define DECODE_SAMSUNG -//#define DECODE_SONY -//#define DECODE_RC5 -//#define DECODE_RC6 -//#define DECODE_BOSEWAVE -//#define DECODE_LEGO_PF -//#define DECODE_MAGIQUEST -//#define DECODE_WHYNTER -//#define DECODE_FAST -//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols -//#define DECODE_HASH // special decoder for all protocols -//#define DECODE_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. +//#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328 +//#define DECODE_JVC // ~ 200 bytes +//#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes +//#define DECODE_LG // ~ 400 bytes +//#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes +//#define DECODE_SAMSUNG // ~ 300 bytes +//#define DECODE_SONY // ~ 175 bytes +//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes +//#define DECODE_RC6 // ~ 375 bytes + +// Universal protocol decoder +//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes +//#define DECODE_HASH // special decoder for all protocols ~ 250 bytes + +// Exotic protocol decoder +//#define DECODE_BOSEWAVE // ~ 140 bytes +//#define DECODE_FAST // ~ 135 bytes +//#define DECODE_LEGO_PF // ~ 300 bytes +//#define DECODE_MAGIQUEST // ~ 270 bytes +//#define DECODE_MARANTZ // RC5 + MARANTZ: ~ 425 bytes +//#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command. ~ 175 bytes +//#define DECODE_WHYNTER // ~ 90 bytes + +//#define DECODE_ONKYO // Decodes NEC and Apple as Onkyo - saves around 90 bytes of program memory, if activated +//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY! ~ 430 bytes +#if FLASHEND >= 0x7FFF // For 16k flash or more, like ATtiny1604. Code does not fit in program memory of ATtiny85 etc. +// Do not enable any protocol explicitly => all protocols are enabled automatically. // !!! Enabling B&O disables detection of Sony, because the repeat gap for SONY is smaller than the B&O frame gap :-( !!! -//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY! +//#define DECODE_BEO // Bang & Olufsen protocol always must be enabled explicitly. It has an IR transmit frequency of 455 kHz! It prevents decoding of SONY! ~ 430 bytes #else // for 8k flash -//#define DECODE_DENON // Includes Sharp -#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 +//#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328 +//#define DECODE_JVC // ~ 200 bytes +#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes +#define DECODE_LG // ~ 400 bytes +#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes +#define DECODE_SAMSUNG // ~ 300 bytes +//#define DECODE_SONY // ~ 175 bytes +//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes +//#define DECODE_RC6 // ~ 375 bytes +#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes +#define DECODE_HASH // special decoder for all protocols ~ 250 bytes + +#define EXCLUDE_EXOTIC_PROTOCOLS // Saves around 90 bytes of program memory, if activated #endif // etc. see IRremote.hpp // #if !defined(RAW_BUFFER_LENGTH) // Use more than the default values of 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM -# if RAMSIZE >= 0x400 -// Here we have 1 k RAM or more -#define RAW_BUFFER_LENGTH 750 +# if RAMSIZE <= 0x400 +// Here we have 1 k RAM or less +#define RAW_BUFFER_LENGTH 360 +# elif RAMSIZE <= 0x800 +// Here we have 2 k RAM or less, otherwise use default of 750 +#define RAW_BUFFER_LENGTH 600 // 400 is OK with Pronto and 1000 is OK without Pronto. 1200 is too much here, because then variables are overwritten. # endif #endif @@ -126,6 +136,13 @@ # endif #endif +/* + * Using the function printActiveIRProtocols() requires additional 314 bytes program memory + * Using the function printIRResultShort() requires additional 1450 bytes program memory + * Using the function printIRSendUsage() requires additional 2736 bytes program memory + * Because these 3 functions all share common code, using all 3 functions requires only additional 3016 bytes program memory + */ + void generateTone(); void handleOverflow(); bool detectLongPress(uint16_t aLongPressDurationMillis); @@ -259,7 +276,7 @@ void loop() { * The info output for a successful receive */ IrReceiver.printIRResultShort(&Serial); - IrReceiver.printIRSendUsage(&Serial); + IrReceiver.printIRSendUsage(&Serial); // Calls printIRResultShort() and other functions, if protocol is UNKNOWN } } #endif // #if FLASHEND >= 0x3FFF diff --git a/examples/SimpleReceiver/SimpleReceiver.ino b/examples/SimpleReceiver/SimpleReceiver.ino index bff3d4749..4c0aeaea1 100644 --- a/examples/SimpleReceiver/SimpleReceiver.ino +++ b/examples/SimpleReceiver/SimpleReceiver.ino @@ -35,39 +35,48 @@ /* * Specify which protocol(s) should be used for decoding. - * If no protocol is defined, all protocols (except Bang&Olufsen) are active. + * If no protocol is defined, all protocols (except BEO / Bang&Olufsen) are active. * This must be done before the #include + * In alphabetic order */ -//#define DECODE_DENON // Includes Sharp -//#define DECODE_JVC -//#define DECODE_KASEIKYO -//#define DECODE_PANASONIC // alias for DECODE_KASEIKYO -//#define DECODE_LG -//#define DECODE_NEC // Includes Apple and Onkyo. 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 DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328 +//#define DECODE_JVC // ~ 200 bytes +//#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes +//#define DECODE_LG // ~ 400 bytes +//#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes +//#define DECODE_SAMSUNG // ~ 300 bytes +//#define DECODE_SONY // ~ 175 bytes +//#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes +//#define DECODE_RC6 // ~ 375 bytes + +// Universal protocol decoder +//#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes +//#define DECODE_HASH // special decoder for all protocols ~ 250 bytes + +// Exotic protocol decoder +//#define DECODE_BOSEWAVE // ~ 140 bytes +//#define DECODE_FAST // ~ 135 bytes +//#define DECODE_LEGO_PF // ~ 300 bytes +//#define DECODE_MAGIQUEST // ~ 270 bytes +//#define DECODE_MARANTZ // RC5 + MARANTZ: ~ 425 bytes +//#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command. ~ 175 bytes +//#define DECODE_WHYNTER // ~ 90 bytes + +//#define DECODE_BEO // This protocol must always be enabled manually, i.e. it is NOT enabled if no protocol is defined. It prevents decoding of SONY! ~ 430 bytes //#define DEBUG // Activate this for lots of lovely debug output from the decoders. -//#define 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. #include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc. Sets FLASHEND and RAMSIZE and evaluates value of SEND_PWM_BY_TIMER. #include // include the library +/* + * Using the function printActiveIRProtocols() requires additional 318 bytes program memory + * Using the function printIRResultShort() requires additional 1436 bytes program memory + * Using the function printIRSendUsage() requires additional 2568 bytes program memory + * Because these 3 functions all share common code, using all 3 functions requires only additional 2884 bytes program memory + */ void setup() { Serial.begin(115200); @@ -78,7 +87,7 @@ void setup() { IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); Serial.print(F("Ready to receive IR signals of protocols: ")); - printActiveIRProtocols(&Serial); + printActiveIRProtocols(&Serial); // Requires additional 318 bytes program memory Serial.println(F("at pin " STR(IR_RECEIVE_PIN))); } @@ -105,8 +114,8 @@ void loop() { } else { IrReceiver.resume(); // Early enable receiving of the next IR frame - IrReceiver.printIRResultShort(&Serial); - IrReceiver.printIRSendUsage(&Serial); + IrReceiver.printIRResultShort(&Serial); // Requires additional 1436 bytes program memory + IrReceiver.printIRSendUsage(&Serial); // Calls printIRResultShort() and other functions, if protocol is UNKNOWN } Serial.println(); diff --git a/examples/UnitTest/UnitTest.ino b/examples/UnitTest/UnitTest.ino index f03dbb895..f88f26227 100644 --- a/examples/UnitTest/UnitTest.ino +++ b/examples/UnitTest/UnitTest.ino @@ -74,18 +74,17 @@ #if FLASHEND >= 0x1FFF // For 8k flash or more, like ATtiny85 #define DECODE_DENON // Includes Sharp -#define DECODE_KASEIKYO -#define DECODE_PANASONIC // alias for DECODE_KASEIKYO -#define DECODE_NEC // Includes Apple and Onkyo +#define DECODE_KASEIKYO // Includes Panasonic ~ 640 bytes +#define DECODE_NEC // Includes Apple and Onkyo ~ 1050 bytes #endif #if FLASHEND >= 0x3FFF // For 16k flash or more, like ATtiny1604 #define DECODE_JVC -#define DECODE_RC5 +#define DECODE_RC5 // with DECODE_MARANTZ ~ 1270 #define DECODE_MARANTZ -#define DECODE_RC6 +#define DECODE_RC6 // ~ 940 bytes -#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols +#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2430 bytes #define DECODE_HASH // special decoder for all protocols #endif @@ -94,20 +93,20 @@ #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 DECODE_BEO // It prevents decoding of SONY (default repeats), which we are not using here. ~ 1340 bytes //#define ENABLE_BEO_WITHOUT_FRAME_GAP // !!!For successful unit testing we must see the warning at ir_BangOlufsen.hpp:100:2!!! -#if defined(DECODE_BEO) +# if defined(DECODE_BEO) #define RECORD_GAP_MICROS 16000 // Force to get the complete frame including the 3. space of 15 ms in the receive buffer #define SUPPRESS_BEO_RECORD_GAP_MICROS_WARNING // We know, what we do here :-) #define BEO_KHZ 38 // We send and receive Bang&Olufsen with 38 kHz instead of 455 kHz in order to be able to test it +# endif #endif -#define DECODE_BOSEWAVE -#define DECODE_MAGIQUEST -#define DECODE_OPENLASIR -#define DECODE_FAST +#define DECODE_BOSEWAVE // ~ 250 bytes +#define DECODE_MAGIQUEST // ~ 460 bytes +#define DECODE_OPENLASIR // ~ 330 bytes +#define DECODE_FAST // ~ 210 bytes //#define DECODE_WHYNTER @@ -382,7 +381,7 @@ void checkReceivedExtra(uint16_t aSentExtra) { void waitForReceived() { // wait until signal has received - uint16_t tTimeoutCounter = 1000; // gives 10 seconds timeout + uint16_t tTimeoutCounter = 500; // gives 5 seconds timeout while (!sDataJustReceived) { delay(10); if (tTimeoutCounter == 0) { @@ -656,7 +655,7 @@ void loop() { delay(DELAY_AFTER_SEND); # endif // defined(DECODE_NEC) -# if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# if defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic 0xB, 0x10 as 48 bit PulseDistance PGM using ProtocolConstants 1=432|1296, 0=432|432")); Serial.flush(); # if __INT_WIDTH__ < 32 @@ -701,7 +700,7 @@ void loop() { # endif delay(DELAY_AFTER_SEND); -# endif // defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +# endif // defined(DECODE_KASEIKYO) # if defined(DECODE_DISTANCE_WIDTH) # if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER) @@ -913,7 +912,7 @@ void loop() { delay(DELAY_AFTER_SEND); #endif -#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +#if defined(DECODE_KASEIKYO) Serial.println(F("Send Panasonic")); Serial.flush(); IrSender.sendPanasonic(sAddress & 0xFFF, sCommand, sRepeats); diff --git a/src/IRFeedbackLED.hpp b/src/IRFeedbackLED.hpp index 5efbc5f6c..058c7285c 100644 --- a/src/IRFeedbackLED.hpp +++ b/src/IRFeedbackLED.hpp @@ -8,7 +8,7 @@ ************************************************************************************* * MIT License * - * Copyright (c) 2021-2022 Armin Joachimsmeyer + * Copyright (c) 2021-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/src/IRProtocol.h b/src/IRProtocol.h index eda5ad441..6b11044b6 100644 --- a/src/IRProtocol.h +++ b/src/IRProtocol.h @@ -45,6 +45,11 @@ * See also SimpleReceiver example */ +// For backward compatibility +#if defined(DECODE_PANASONIC) +#define DECODE_KASEIKYO +#endif + #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) \ @@ -54,31 +59,31 @@ || defined(DECODE_OPENLASIR))) /* * If no protocol is explicitly enabled, we enable all protocols + * In alphabetic order: */ -#define DECODE_DENON // Includes Sharp -#define DECODE_JVC -#define DECODE_KASEIKYO -#define DECODE_PANASONIC // alias for DECODE_KASEIKYO -#define DECODE_LG -#define DECODE_NEC // Includes Apple and Onkyo -#define DECODE_SAMSUNG -#define DECODE_SONY -#define DECODE_RC5 -#define DECODE_RC6 +#define DECODE_DENON // Includes Sharp - requires around 250 bytes of program memory on ATmega328 +#define DECODE_JVC // ~ 200 bytes +#define DECODE_KASEIKYO // Includes Panasonic ~ 300 bytes +#define DECODE_LG // ~ 400 bytes +#define DECODE_NEC // Includes Apple and Onkyo ~ 250 bytes +#define DECODE_SAMSUNG // ~ 300 bytes +#define DECODE_SONY // ~ 175 bytes +#define DECODE_RC5 // RC5 + MARANTZ: ~ 425 bytes +#define DECODE_RC6 // ~ 375 bytes # 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_MARANTZ -#define DECODE_FAST -#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command +#define DECODE_BOSEWAVE // ~ 140 bytes +#define DECODE_FAST // ~ 135 bytes +#define DECODE_LEGO_PF // ~ 300 bytes +#define DECODE_MAGIQUEST // ~ 270 bytes +#define DECODE_MARANTZ // RC5 + MARANTZ: ~ 425 bytes +#define DECODE_OPENLASIR // Modified NEC with 8-bit validated address + 16-bit command. ~ 175 bytes +#define DECODE_WHYNTER // ~ 90 bytes # 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 +#define DECODE_DISTANCE_WIDTH // Universal decoder for pulse distance width protocols ~ 2275 bytes +#define DECODE_HASH // special decoder for all protocols ~ 250 bytes # endif # endif #endif // !defined(NO_DECODER) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index c281b31d1..5b3b3aa99 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -590,7 +590,7 @@ bool IRrecv::decode() { } #endif -#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +#if defined(DECODE_KASEIKYO) TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode")); if (decodeKaseikyo()) { return true; @@ -1537,7 +1537,7 @@ void printActiveIRProtocols(Print *aSerial) { #elif defined(DECODE_NEC) aSerial->print(F("NEC/NEC2/Onkyo/Apple, ")); #endif -#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) +#if defined(DECODE_KASEIKYO) aSerial->print(F("Panasonic/Kaseikyo, ")); #endif #if defined(DECODE_DENON) @@ -2125,7 +2125,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) { } } -#if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6) || defined(DECODE_MARANTZ) +#if defined(DECODE_KASEIKYO) || defined(DECODE_RC6) || defined(DECODE_MARANTZ) if ((decodedIRData.flags & IRDATA_FLAGS_EXTRA_INFO) && (decodedIRData.protocol == KASEIKYO || decodedIRData.protocol == RC6A || decodedIRData.protocol == MARANTZ)) { // Vendor code, Customer or MarantzExtension parameter, which is after numberOfRepeats parameter aSerial->print(F(", 0x")); @@ -2291,7 +2291,6 @@ void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsI aSerial->println(F(" ticks")); } aSerial->println(); - } /** diff --git a/src/ir_NEC.hpp b/src/ir_NEC.hpp index 60ea75988..cdf5a951d 100644 --- a/src/ir_NEC.hpp +++ b/src/ir_NEC.hpp @@ -279,7 +279,7 @@ bool IRrecv::decodeNEC() { tValue.ULong = decodedIRData.decodedRawData; decodedIRData.command = tValue.UByte.MidHighByte; // 8 bit -#if defined(DECODE_ONKYO) +#if defined(DECODE_ONKYO) // Decodes NEC and Apple as Onkyo // Here only Onkyo protocol is supported -> force 16 bit address and command decoding. No NEC decoding possible! decodedIRData.address = tValue.UWord.LowWord; // first 16 bit decodedIRData.protocol = ONKYO; diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index b0b224919..9db66ee3b 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -200,10 +200,9 @@ void disableSendPWMByTimer() { # endif #elif defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1604__) || defined(__AVR_ATtiny1614__) || defined(__AVR_ATtiny1624__) \ - || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // e.g. TinyCore boards + || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) || defined(__AVR_ATtiny3227__) // e.g. TinyCore boards # if !defined(IR_USE_AVR_TIMER_A) && !defined(IR_USE_AVR_TIMER_D) #define IR_USE_AVR_TIMER_A // use this if you use megaTinyCore, Tone is on TCB and millis() on TCD -//#define IR_USE_AVR_TIMER_D // use this if you use TinyCore # endif // ATmega8u2, ATmega16U2, ATmega32U2, ATmega8 - Timer 2 does not work with existing code below From 498dc591b255d8ba2e239c875804bdab2ab0fe91 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 8 Apr 2026 23:12:44 +0200 Subject: [PATCH 128/133] Bumped version to 4.7.1 - Changed wrong &Serial to aSerial at 2 places. --- changelog.md | 3 +++ library.json | 2 +- library.properties | 2 +- src/IRCommandDispatcher.hpp | 2 +- src/IRReceive.hpp | 2 +- src/IRVersion.h | 4 ++-- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index 1a4a549f9..c20528f30 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,9 @@ The latest version may not be released! See also the commit log at github: https://github.com/Arduino-IRremote/Arduino-IRremote/commits/master +# 4.7.1 +- Changed wrong &Serial to aSerial at 2 places. + # 4.7.0 - Added removed typedef `IRRawDataType` for backward compatibility. - Modified and renamed function `setToggleBitValueForRC5AndRC6()` to `setNextToggleBitValueForRC5AndRC6()`. diff --git a/library.json b/library.json index 56184158c..e621f7c06 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "IRremote", - "version": "4.7.0", + "version": "4.7.1", "description": "Send and receive infrared signals with multiple protocols", "keywords": "communication, infrared, ir, remote", "homepage": "https://github.com/Arduino-IRremote/Arduino-IRremote", diff --git a/library.properties b/library.properties index e15d59b05..f0beef631 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=IRremote -version=4.7.0 +version=4.7.1 author=shirriff, z3t0, ArminJo maintainer=Armin Joachimsmeyer sentence=Send and receive infrared signals with multiple protocols diff --git a/src/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp index bbc104197..86660dfc5 100644 --- a/src/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -278,7 +278,7 @@ void IRCommandDispatcher::printIRInfo(Print *aSerial) { aSerial->println(F("Listening to IR remote at pin " STR(IRMP_INPUT_PIN))); # endif aSerial->print(F("Accepted protocols are: ")); - irmp_print_active_protocols(&Serial); + irmp_print_active_protocols(aSerial); aSerial->println(); #else # if defined(IR_REMOTE_NAME) diff --git a/src/IRReceive.hpp b/src/IRReceive.hpp index 5b3b3aa99..f2b2bf4a6 100644 --- a/src/IRReceive.hpp +++ b/src/IRReceive.hpp @@ -2020,7 +2020,7 @@ void IRrecv::printIRSendUsage(Print *aSerial) { if (decodedIRData.protocol == UNKNOWN){ aSerial->println(); aSerial->print(F(" ")); - printIRResultAsCArray(&Serial); + printIRResultAsCArray(aSerial); aSerial->print(F(" ")); } aSerial->print(F("IrSender.send")); diff --git a/src/IRVersion.h b/src/IRVersion.h index 0a74f65d6..8dc76ab92 100644 --- a/src/IRVersion.h +++ b/src/IRVersion.h @@ -36,10 +36,10 @@ #ifndef _IR_VERSION_HPP #define _IR_VERSION_HPP -#define VERSION_IRREMOTE "4.7.0" +#define VERSION_IRREMOTE "4.7.1" #define VERSION_IRREMOTE_MAJOR 4 #define VERSION_IRREMOTE_MINOR 7 -#define VERSION_IRREMOTE_PATCH 0 +#define VERSION_IRREMOTE_PATCH 1 /* * Macro to convert 3 version parts into an integer From 237ab86a7fbfe612e1322bdff6d2b218c24acb09 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Thu, 4 Jun 2026 12:14:36 +0200 Subject: [PATCH 129/133] Documentation --- README.md | 27 +++++++++++++++++++++++++ examples/AllProtocolsOnLCD/ADCUtils.hpp | 5 +++-- src/IRremoteInt.h | 5 ----- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 91c36ff2e..37ddb6806 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr * [Multiple IR receivers](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#multiple-ir-receivers) - [Sending IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-ir-codes) * [Sending UNKNOWN protocol](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-unknown-protocol) + * [Sending protocol from description](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-protocol-from-description) * [Sending IRDB IR codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#sending-irdb-ir-codes) + [List of public IR code databases](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#list-of-public-ir-code-databases) * [Flipper Zero Codes](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#flipper-zero-codes) @@ -624,6 +625,32 @@ you can store the timing sequence in an array and send it with IrSender.sendRaw( like done in [SendDemo](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendDemo/SendDemo.ino#L180). Do not forget to send repeats. +## Sending protocol from description +If you only have the description of the protocol, but no sender which can generate the IR codes, +then you can try to send the protocol with: + +``` +sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, + uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, + IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, + int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = nullptr) +``` + +E.g. for the CDTV IR Keyboard protocol a description can be found [here](https://github.com/Korinel/Amiga-CDTV-IR-Keyboard). +Thus, the right parameters for CDTV IR Keyboard Protocol on a 32 bit platform are: + +``` +sendPulseDistanceWidth(40, 9000, 4500, 1200, 400, 400, 400, , 40, + IRDATA_FLAGS_IS_MSB_FIRST, 110, 3); // 110 and 3 are guessed values! +``` + +On an 8 bit platform, you must store the 40 bits into an array of two 32 bit unsigned integers and send it with: + +``` +sendPulseDistanceWidthFromArray(40, 9000, 4500, 1200, 400, 400, 400,
40, + IRDATA_FLAGS_IS_MSB_FIRST, 110, 3); // 110 and 3 are guessed values! +``` + ## Sending IRDB IR codes The codes found in the [irdb database](https://github.com/probonopd/irdb/tree/master/codes) specify a **device**, a **subdevice** and a **function**. Most of the times, *device* and *subdevice* can be taken as upper and lower byte of the **address parameter** and *function* diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index 12357992c..b3adab6ca 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -41,9 +41,10 @@ /* * By replacing this value with the voltage you measured a the AREF pin after a conversion * with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV. + * If value > real AREF voltage, measured values are > real values */ #if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT) -#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100 // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values +#define ADC_INTERNAL_REFERENCE_MILLIVOLT 1100 // Change to value measured at the AREF pin. #endif // Union to speed up the combination of low and high bytes to a word @@ -78,7 +79,7 @@ union WordUnionForADCUtils { * Persistent storage for VCC value */ float sVCCVoltage; -uint16_t sVCCVoltageMillivolt; +uint16_t sVCCVoltageMillivolt; // Set by readVCCVoltageMillivoltSimple(), readVCCVoltageMillivolt() // for isVCCTooLowMultipleTimes() long sLastVCCCheckMillis; diff --git a/src/IRremoteInt.h b/src/IRremoteInt.h index 33910cf45..676cfd423 100644 --- a/src/IRremoteInt.h +++ b/src/IRremoteInt.h @@ -581,11 +581,6 @@ class IRsend { uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags, uint16_t aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats, void (*aSpecialSendRepeatFunction)() = nullptr); - void sendPulseDistanceWidth(uint_fast8_t aFrequencyKHz, uint16_t aHeaderMarkMicros, uint16_t aHeaderSpaceMicros, - uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, - IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, bool aMSBFirst, bool aSendStopBit, uint16_t aRepeatPeriodMillis, - 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, IRDecodedRawDataType aData, uint_fast8_t aNumberOfBits, uint8_t aFlags); void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits, bool aSendStartBit = true); From b90a3b448b8f190e2f1523fe5b53158417ce5afc Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 24 Jun 2026 20:38:14 +0200 Subject: [PATCH 130/133] Fix bug #1354 RP2040 - when USE_NO_SEND_PWM was set, SEND_PWM_BY_TIMER was re-enabled --- src/private/IRTimer.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/private/IRTimer.hpp b/src/private/IRTimer.hpp index 9db66ee3b..0e951f0b6 100644 --- a/src/private/IRTimer.hpp +++ b/src/private/IRTimer.hpp @@ -1990,7 +1990,10 @@ void timerDisableReceiveInterrupt() { void timerConfigForReceive() { // no need for initializing timer at setup() } + +#if !defined(USE_NO_SEND_PWM) #define SEND_PWM_BY_TIMER // Disable carrier PWM generation in software and use (restricted) hardware PWM. +#endif # if defined(SEND_PWM_BY_TIMER) #include "hardware/pwm.h" From f2f8de414b8e2724c578377e651b6e5c1fefb7b2 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sat, 27 Jun 2026 09:27:58 +0200 Subject: [PATCH 131/133] Separated migrating guide --- Migrating.md | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 185 ++----------------------------------------------- 2 files changed, 197 insertions(+), 180 deletions(-) create mode 100644 Migrating.md diff --git a/Migrating.md b/Migrating.md new file mode 100644 index 000000000..8b3177658 --- /dev/null +++ b/Migrating.md @@ -0,0 +1,192 @@ +# Migrating legacy projects to the latest version + +## Table of contents + * [New features and changes in version 4.6](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-version-46) + * [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 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) + +This library has been refactored, breaking backward compatibility with the old version, on which many examples on the Internet are based.
+If your code uses `irrecv.decode(&results)`, it is written for Version 2.x. This library (Version 4.x) now uses a simpler `IrReceiver.decode()` syntax. See the Conversion guide below. + +## New features and changes in version 4.6 +** Version 4.5.0 does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt.** +- Support for **multiple receiver instances**.
+`irparams_struct irparams` is now member of `IRrecv`. Thus `rawDataPtr` (pointer to irparams) was removed from `IrReceiver.decodedIRData`.
+Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.rawbuf`, the same holds for `IrReceiver.irparams.rawlen`. +- LED feedback is always enabled for sending. It can only be disabled by using `#define NO_LED_SEND_FEEDBACK_CODE` or `#define NO_LED_FEEDBACK_CODE`. +- The second parameter of the function `IrSender.begin(uint_fast8_t aSendPin, bool aEnableLEDFeedback)` has changed to `uint_fast8_t aFeedbackLEDPin`. Therefore this function call no longer works as expected because it uses the old boolean value of e.g. `ENABLE_LED_FEEDBACK` which evaluates to true or 1 as pin number of the LED feedback pin number. +- New experimental Velux send function. +- Send function for Marantz version of the RC5x protocol. This protocol has an additional 6 bit command extension and adds a short pause after the address is sent to identify this variant of the protocol. + +## 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. +- **Callback** after receiving a command - It calls your code as soon as a frame was received. +- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. +- New FAST protocol. +- Automatic printout of the **corresponding send function** with `printIRSendUsage()`. + +### Converting your 3.x program to the 4.x version +- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder). +- The parameter `bool hasStopBit` is no longer required and removed e.g. for function `sendPulseDistanceWidth()`. + +## 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 a 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/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 existing receiving devices without using IR. +- Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
+ Reduces memory footprint and decreases decoding time. +- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**. + +[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries). + +
+ +## Converting your 2.x program to the 4.x version +Starting with the 3.1 version, **the generation of PWM for sending is done by software**, thus saving the hardware timer and **enabling arbitrary output pins for sending**.
+If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, +if you get false error messages regarding begin() during compilation. + +- **IRreceiver** and **IRsender** object have been added and can be used without defining them, like the well known Arduino **Serial** object. +- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`. +- 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().
+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.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 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: + +```c++ +#include +#define RECV_PIN 2 + +IRrecv irrecv(RECV_PIN); +decode_results results; + +void setup() +{ +... + Serial.begin(115200); // Establish serial communication + irrecv.enableIRIn(); // Start the receiver +} + +void loop() { + if (irrecv.decode(&results)) { + Serial.println(results.value, HEX); + ... + irrecv.resume(); // Receive the next value + } + ... +} +``` + +#### New 4.x program: + +```c++ +#include +#define IR_RECEIVE_PIN 2 + +void setup() +{ +... + Serial.begin(115200); // // Establish serial communication + IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver +} + +void loop() { + if (IrReceiver.decode()) { + Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data + IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line + IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data + ... + IrReceiver.resume(); // Enable receiving of the next value + } + ... +} +``` + +#### 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 nibble (4 bit / Hex numbers) positions and then reverse all bit positions of each nibble or write it as one binary string and reverse/mirror it.
+This can be done by using the new functions `bitreverseOneByte()` or `bitreverse32Bit()`. + +### Nibble reverse +`0xCB 34 01 02` MSB value
+`0x20 10 43 BC` after nibble reverse
+`0x40 80 2C D3` LSB value after bit reverse of each nibble + +### Nibble reverse map +``` + 0->0 1->8 2->4 3->C + 4->2 5->A 6->6 7->E + 8->1 9->9 A->5 B->D + C->3 D->B E->7 F->F +``` + +### Binary string reverse +If you **read the first binary sequence backwards** (right to left), you get the second sequence.
+`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
+`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`. + +### Online tool which reverses every byte, but not the order of the bytes +Use this [tool provided by analysir](https://www.analysir.com/hex2nec.php). + +### Send MSB directly +Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`. + +
+ +## Errors when using the 4.x versions for old tutorials +If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, +just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
+Most likely your code will run and you will not miss the new features. + +
+ +## Staying on 2.x +Consider using the [original 2.4 release from 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) +or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
+It may be sufficient and deals flawlessly with 32 bit IR codes.
+If this doesn't work for you, you can be sure that 4.x is trying to be compatible with earlier versions, so your old examples should work just fine. + +### Drawbacks of using 2.x +- Only the following decoders are available:
+ ` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
+ ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` +- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. +- No decoding to a more meaningful (constant) 8/16 bit address and 8 bit command. diff --git a/README.md b/README.md index 37ddb6806..9b3d9c64a 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,8 @@ Available as [Arduino library "IRremote"](https://www.arduinolibraries.info/libr # Table of contents - [Supported IR Protocols](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#supported-ir-protocols) - [Common issues when using IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#common-issues-when-using-irremote) -- [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#migrating-legacy-projects-to-the-latest-version) +- [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Migrating.md) * [New features and changes in version 4.6](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#new-features-and-changes-in-version-46) - * [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 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 files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#why-hpp-instead-of-cpp-files) - [Using the new *.hpp files](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#using-the-new-hpp-files) - [Tutorials](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#tutorials) @@ -131,9 +125,9 @@ Or *"I build a gadget with 2 motors controlled by IR and the [IR stops after the 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. -# Migrating legacy projects to the latest version -This library has been refactored, breaking backward compatibility with the old version, on which many examples on the Internet are based.
-If your code uses `irrecv.decode(&results)`, it is written for Version 2.x. This library (Version 4.x) now uses a simpler `IrReceiver.decode()` syntax. See the Conversion guide below. +
+ +# [Migrating legacy projects to the latest version](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/Migrating.md) ## New features and changes in version 4.6 ** Version 4.5.0 does not work for ESP platform, because of missing ESP IRAM_ATTR for receiving interrupt.** @@ -143,176 +137,7 @@ Old `IrReceiver.decodedIRData.rawDataPtr->rawbuf` is now `IrReceiver.irparams.ra - 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. -- **Callback** after receiving a command - It calls your code as soon as a frame was received. -- Improved handling of `PULSE_DISTANCE` + `PULSE_WIDTH` protocols. -- New FAST protocol. -- Automatic printout of the **corresponding send function** with `printIRSendUsage()`. - -### Converting your 3.x program to the 4.x version -- You must replace `#define DECODE_DISTANCE` by `#define DECODE_DISTANCE_WIDTH` (only if you explicitly enabled this decoder). -- The parameter `bool hasStopBit` is no longer required and removed e.g. for function `sendPulseDistanceWidth()`. - -## 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 a 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/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 existing receiving devices without using IR. -- Easy protocol configuration, **directly in your [source code](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SimpleReceiver/SimpleReceiver.ino#L33-L57)**.
- Reduces memory footprint and decreases decoding time. -- Contains a [very small NEC only decoder](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#minimal-nec-receiver), which **does not require any timer resource**. - -[-> Feature comparison of 5 Arduino IR libraries](https://github.com/Arduino-IRremote/Arduino-IRremote?tab=readme-ov-file#quick-comparison-of-5-arduino-ir-receiving-libraries). - -
- -## Converting your 2.x program to the 4.x version -Starting with the 3.1 version, **the generation of PWM for sending is done by software**, thus saving the hardware timer and **enabling arbitrary output pins for sending**.
-If you use an (old) Arduino core that does not use the `-flto` flag for compile, you can activate the line `#define SUPPRESS_ERROR_MESSAGE_FOR_BEGIN` in IRRemote.h, -if you get false error messages regarding begin() during compilation. - -- **IRreceiver** and **IRsender** object have been added and can be used without defining them, like the well known Arduino **Serial** object. -- Just remove the line `IRrecv IrReceiver(IR_RECEIVE_PIN);` and/or `IRsend IrSender;` in your program and replace all occurrences of `IRrecv.` or `irrecv.` with `IrReceiver` and replace all `IRsend` or `irsend` with `IrSender`. -- 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().
-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.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 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: - -```c++ -#include -#define RECV_PIN 2 - -IRrecv irrecv(RECV_PIN); -decode_results results; - -void setup() -{ -... - Serial.begin(115200); // Establish serial communication - irrecv.enableIRIn(); // Start the receiver -} - -void loop() { - if (irrecv.decode(&results)) { - Serial.println(results.value, HEX); - ... - irrecv.resume(); // Receive the next value - } - ... -} -``` - -#### New 4.x program: - -```c++ -#include -#define IR_RECEIVE_PIN 2 - -void setup() -{ -... - Serial.begin(115200); // // Establish serial communication - IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver -} - -void loop() { - if (IrReceiver.decode()) { - Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data - IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line - IrReceiver.printIRSendUsage(&Serial); // Print the statement required to send this data - ... - IrReceiver.resume(); // Enable receiving of the next value - } - ... -} -``` - -#### 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 nibble (4 bit / Hex numbers) positions and then reverse all bit positions of each nibble or write it as one binary string and reverse/mirror it.
-This can be done by using the new functions `bitreverseOneByte()` or `bitreverse32Bit()`. - -### Nibble reverse -`0xCB 34 01 02` MSB value
-`0x20 10 43 BC` after nibble reverse
-`0x40 80 2C D3` LSB value after bit reverse of each nibble - -### Nibble reverse map -``` - 0->0 1->8 2->4 3->C - 4->2 5->A 6->6 7->E - 8->1 9->9 A->5 B->D - C->3 D->B E->7 F->F -``` - -### Binary string reverse -If you **read the first binary sequence backwards** (right to left), you get the second sequence.
-`0xCB340102` is binary `1100 1011 0011 0100 0000 0001 0000 0010`.
-`0x40802CD3` is binary `0100 0000 1000 0000 0010 1100 1101 0011`. - -### Online tool which reverses every byte, but not the order of the bytes -Use this [tool provided by analysir](https://www.analysir.com/hex2nec.php). - -### Send MSB directly -Sending old MSB codes without conversion can be done by using `sendNECMSB()`, `sendSonyMSB()`, `sendSamsungMSB()`, `sendJVCMSB()`. - -
- -## Errors when using the 4.x versions for old tutorials -If you suffer from errors with old tutorial code including `IRremote.h` instead of `IRremote.hpp`, -just try to rollback to [Version 2.4.0](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0).
-Most likely your code will run and you will not miss the new features. - -
- -## Staying on 2.x -Consider using the [original 2.4 release from 2017](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/v2.4.0) -or the last backwards compatible [2.8 version](https://github.com/Arduino-IRremote/Arduino-IRremote/releases/tag/2.8.0) for you project.
-It may be sufficient and deals flawlessly with 32 bit IR codes.
-If this doesn't work for you, you can be sure that 4.x is trying to be compatible with earlier versions, so your old examples should work just fine. - -### Drawbacks of using 2.x -- Only the following decoders are available:
- ` NEC `     ` Denon `     ` Panasonic `     ` JVC `     ` LG `
- ` RC5 `     ` RC6 `     ` Samsung `     ` Sony ` -- The call of `irrecv.decode(&results)` uses the old MSB first decoders like in 2.x and sets the 32 bit codes in `results.value`. -- No decoding to a more meaningful (constant) 8/16 bit address and 8 bit command. +- 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.
From fa33f2fd9731ac0e1c0a6bc76ab20135791adab8 Mon Sep 17 00:00:00 2001 From: ArminJo Date: Sun, 2 Aug 2026 22:23:04 +0200 Subject: [PATCH 132/133] Housekeeping --- examples/AllProtocolsOnLCD/ADCUtils.h | 1 - examples/AllProtocolsOnLCD/ADCUtils.hpp | 1 - examples/AllProtocolsOnLCD/LCDPrintUtils.hpp | 1 - examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h | 1 - examples/CallbackDemo/PinDefinitionsAndMore.h | 1 - examples/ControlRelay/PinDefinitionsAndMore.h | 1 - examples/IRDispatcherDemo/DemoIRCommandMapping.h | 1 - examples/IRDispatcherDemo/IRDispatcherDemo.ino | 1 - examples/IRDispatcherDemo/PinDefinitionsAndMore.h | 1 - examples/IRremoteExtensionTest/PinDefinitionsAndMore.h | 1 - examples/MicroGirs/PinDefinitionsAndMore.h | 1 - examples/MultipleReceivers/PinDefinitionsAndMore.h | 1 - examples/ReceiveAndSend/PinDefinitionsAndMore.h | 1 - examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h | 1 - examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h | 1 - examples/ReceiveDemo/PinDefinitionsAndMore.h | 1 - examples/ReceiveDump/PinDefinitionsAndMore.h | 1 - examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h | 1 - examples/SendAndReceive/PinDefinitionsAndMore.h | 1 - examples/SendBoseWaveDemo/PinDefinitionsAndMore.h | 1 - examples/SendDemo/PinDefinitionsAndMore.h | 1 - examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h | 1 - examples/SendProntoDemo/PinDefinitionsAndMore.h | 1 - examples/SendRawDemo/PinDefinitionsAndMore.h | 1 - examples/SimpleReceiver/PinDefinitionsAndMore.h | 1 - examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h | 1 - examples/SimpleSender/PinDefinitionsAndMore.h | 1 - examples/SimpleSender/SimpleSender.ino | 1 - examples/TinyReceiver/PinDefinitionsAndMore.h | 1 - examples/TinyReceiver/TinyReceiver.ino | 2 +- examples/TinySender/PinDefinitionsAndMore.h | 1 - examples/TinySender/TinySender.ino | 2 +- examples/UnitTest/PinDefinitionsAndMore.h | 1 - src/IRCommandDispatcher.h | 1 - src/IRCommandDispatcher.hpp | 1 - src/LocalDebugLevelEnd.h | 1 - src/LocalDebugLevelStart.h | 1 - src/LongUnion.h | 1 - src/TinyIR.h | 3 +-- src/TinyIRReceiver.hpp | 2 +- src/TinyIRSender.hpp | 2 +- 41 files changed, 5 insertions(+), 42 deletions(-) diff --git a/examples/AllProtocolsOnLCD/ADCUtils.h b/examples/AllProtocolsOnLCD/ADCUtils.h index 013349b2d..38aa471eb 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.h +++ b/examples/AllProtocolsOnLCD/ADCUtils.h @@ -2,7 +2,6 @@ * ADCUtils.h * * Copyright (C) 2016-2022 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/examples/AllProtocolsOnLCD/ADCUtils.hpp b/examples/AllProtocolsOnLCD/ADCUtils.hpp index b3adab6ca..ef9aad8da 100644 --- a/examples/AllProtocolsOnLCD/ADCUtils.hpp +++ b/examples/AllProtocolsOnLCD/ADCUtils.hpp @@ -4,7 +4,6 @@ * ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h. * * Copyright (C) 2016-2023 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp index a4736bd10..84b78300b 100644 --- a/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp +++ b/examples/AllProtocolsOnLCD/LCDPrintUtils.hpp @@ -5,7 +5,6 @@ * Sets symbols USE_SERIAL_LCD or USE_PARALLEL_LCD and LCD_COLUMNS and LCD_ROWS * * Copyright (C) 2024-2025 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h +++ b/examples/AllProtocolsOnLCD/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/CallbackDemo/PinDefinitionsAndMore.h b/examples/CallbackDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/CallbackDemo/PinDefinitionsAndMore.h +++ b/examples/CallbackDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ControlRelay/PinDefinitionsAndMore.h b/examples/ControlRelay/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ControlRelay/PinDefinitionsAndMore.h +++ b/examples/ControlRelay/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/IRDispatcherDemo/DemoIRCommandMapping.h b/examples/IRDispatcherDemo/DemoIRCommandMapping.h index 4e473b007..38b344752 100644 --- a/examples/IRDispatcherDemo/DemoIRCommandMapping.h +++ b/examples/IRDispatcherDemo/DemoIRCommandMapping.h @@ -4,7 +4,6 @@ * Contains IR remote button codes, strings, and the mapping of codes to functions to call by the dispatcher * * Copyright (C) 2019-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. diff --git a/examples/IRDispatcherDemo/IRDispatcherDemo.ino b/examples/IRDispatcherDemo/IRDispatcherDemo.ino index 81ddf02af..3ec5d8b81 100644 --- a/examples/IRDispatcherDemo/IRDispatcherDemo.ino +++ b/examples/IRDispatcherDemo/IRDispatcherDemo.ino @@ -4,7 +4,6 @@ * Example how to use IRCommandDispatcher to receive IR commands and map them to different actions / functions by means of a mapping array. * * Copyright (C) 2020-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. diff --git a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/IRDispatcherDemo/PinDefinitionsAndMore.h +++ b/examples/IRDispatcherDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h +++ b/examples/IRremoteExtensionTest/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/MicroGirs/PinDefinitionsAndMore.h b/examples/MicroGirs/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/MicroGirs/PinDefinitionsAndMore.h +++ b/examples/MicroGirs/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/MultipleReceivers/PinDefinitionsAndMore.h b/examples/MultipleReceivers/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/MultipleReceivers/PinDefinitionsAndMore.h +++ b/examples/MultipleReceivers/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveAndSend/PinDefinitionsAndMore.h b/examples/ReceiveAndSend/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveAndSend/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSend/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendDistanceWidth/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h +++ b/examples/ReceiveAndSendHob2Hood/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveDemo/PinDefinitionsAndMore.h b/examples/ReceiveDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveDemo/PinDefinitionsAndMore.h +++ b/examples/ReceiveDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveDump/PinDefinitionsAndMore.h b/examples/ReceiveDump/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveDump/PinDefinitionsAndMore.h +++ b/examples/ReceiveDump/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h +++ b/examples/ReceiveOneAndSendMultiple/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendAndReceive/PinDefinitionsAndMore.h b/examples/SendAndReceive/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendAndReceive/PinDefinitionsAndMore.h +++ b/examples/SendAndReceive/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h +++ b/examples/SendBoseWaveDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendDemo/PinDefinitionsAndMore.h b/examples/SendDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendDemo/PinDefinitionsAndMore.h +++ b/examples/SendDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h +++ b/examples/SendLGAirConditionerDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendProntoDemo/PinDefinitionsAndMore.h b/examples/SendProntoDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendProntoDemo/PinDefinitionsAndMore.h +++ b/examples/SendProntoDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SendRawDemo/PinDefinitionsAndMore.h b/examples/SendRawDemo/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SendRawDemo/PinDefinitionsAndMore.h +++ b/examples/SendRawDemo/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SimpleReceiver/PinDefinitionsAndMore.h b/examples/SimpleReceiver/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SimpleReceiver/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiver/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h +++ b/examples/SimpleReceiverForHashCodes/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SimpleSender/PinDefinitionsAndMore.h b/examples/SimpleSender/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/SimpleSender/PinDefinitionsAndMore.h +++ b/examples/SimpleSender/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/SimpleSender/SimpleSender.ino b/examples/SimpleSender/SimpleSender.ino index 7632ca3aa..ac372582e 100644 --- a/examples/SimpleSender/SimpleSender.ino +++ b/examples/SimpleSender/SimpleSender.ino @@ -6,7 +6,6 @@ * Sending IR codes using several pins for sending is implements in the MultipleSendPins example. * * Copyright (C) 2020-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/TinyReceiver/PinDefinitionsAndMore.h b/examples/TinyReceiver/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/TinyReceiver/PinDefinitionsAndMore.h +++ b/examples/TinyReceiver/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/TinyReceiver/TinyReceiver.ino b/examples/TinyReceiver/TinyReceiver.ino index 079600b72..f3465d5aa 100644 --- a/examples/TinyReceiver/TinyReceiver.ino +++ b/examples/TinyReceiver/TinyReceiver.ino @@ -21,7 +21,7 @@ * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. - * This file is also part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License diff --git a/examples/TinySender/PinDefinitionsAndMore.h b/examples/TinySender/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/TinySender/PinDefinitionsAndMore.h +++ b/examples/TinySender/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/examples/TinySender/TinySender.ino b/examples/TinySender/TinySender.ino index a06f9c33b..45d79af76 100644 --- a/examples/TinySender/TinySender.ino +++ b/examples/TinySender/TinySender.ino @@ -18,7 +18,7 @@ * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. - * This file is also part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License diff --git a/examples/UnitTest/PinDefinitionsAndMore.h b/examples/UnitTest/PinDefinitionsAndMore.h index 3dcce3ea8..d3dd74992 100644 --- a/examples/UnitTest/PinDefinitionsAndMore.h +++ b/examples/UnitTest/PinDefinitionsAndMore.h @@ -5,7 +5,6 @@ * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * diff --git a/src/IRCommandDispatcher.h b/src/IRCommandDispatcher.h index ad77b7895..f4f89d26d 100644 --- a/src/IRCommandDispatcher.h +++ b/src/IRCommandDispatcher.h @@ -6,7 +6,6 @@ * To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" * * Copyright (C) 2019-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * This file is part of IRMP https://github.com/IRMP-org/IRMP. diff --git a/src/IRCommandDispatcher.hpp b/src/IRCommandDispatcher.hpp index 86660dfc5..0a65efd3e 100644 --- a/src/IRCommandDispatcher.hpp +++ b/src/IRCommandDispatcher.hpp @@ -12,7 +12,6 @@ * The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands(). * * Copyright (C) 2019-2026 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * This file is part of IRMP https://github.com/IRMP-org/IRMP. diff --git a/src/LocalDebugLevelEnd.h b/src/LocalDebugLevelEnd.h index ff64634f8..e1f1de534 100644 --- a/src/LocalDebugLevelEnd.h +++ b/src/LocalDebugLevelEnd.h @@ -3,7 +3,6 @@ * Undefine local macros at the end of an included (.hpp) file * * Copyright (C) 2024 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/src/LocalDebugLevelStart.h b/src/LocalDebugLevelStart.h index 50569fbf8..9427af71e 100644 --- a/src/LocalDebugLevelStart.h +++ b/src/LocalDebugLevelStart.h @@ -11,7 +11,6 @@ * LOCAL_ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. * * Copyright (C) 2024-2026 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/src/LongUnion.h b/src/LongUnion.h index 8f90f6135..ce4837085 100644 --- a/src/LongUnion.h +++ b/src/LongUnion.h @@ -2,7 +2,6 @@ * LongUnion.h * * Copyright (C) 2020-2022 Armin Joachimsmeyer - * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * diff --git a/src/TinyIR.h b/src/TinyIR.h index d26a31331..f56877fd8 100644 --- a/src/TinyIR.h +++ b/src/TinyIR.h @@ -3,10 +3,9 @@ * * * Copyright (C) 2021-2025 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. - * This file is also part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of IRMP https://github.com/IRMP-org/IRMP. * * TinyIRReceiver is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/TinyIRReceiver.hpp b/src/TinyIRReceiver.hpp index a378fa1b8..0aabb7396 100644 --- a/src/TinyIRReceiver.hpp +++ b/src/TinyIRReceiver.hpp @@ -23,7 +23,7 @@ * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. - * This file is also part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License diff --git a/src/TinyIRSender.hpp b/src/TinyIRSender.hpp index 1ed865f20..a9ae84f4a 100644 --- a/src/TinyIRSender.hpp +++ b/src/TinyIRSender.hpp @@ -14,7 +14,7 @@ * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. - * This file is also part of IRMP https://github.com/IRMP-org/IRMP. + * This file is part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License From 6158d6587024269aa79ae66e02c71bbb7b1e7fbd Mon Sep 17 00:00:00 2001 From: ArminJo Date: Wed, 12 Aug 2026 11:01:20 +0200 Subject: [PATCH 133/133] Added RC6A in write(IRData *aIRSendData,... --- examples/MultipleSendPins/MultipleSendPins.ino | 1 - examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino | 1 - src/IRSend.hpp | 5 ++++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/MultipleSendPins/MultipleSendPins.ino b/examples/MultipleSendPins/MultipleSendPins.ino index 30a627ef7..ce7b7827a 100644 --- a/examples/MultipleSendPins/MultipleSendPins.ino +++ b/examples/MultipleSendPins/MultipleSendPins.ino @@ -5,7 +5,6 @@ * 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. * diff --git a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino index 6ed6ba1c6..99e67014e 100644 --- a/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino +++ b/examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino @@ -11,7 +11,6 @@ * * * Copyright (C) 2019-2020 Armin Joachimsmeyer - * armin.joachimsmeyer@gmail.com * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. diff --git a/src/IRSend.hpp b/src/IRSend.hpp index 7aaa92c8f..82ae85550 100644 --- a/src/IRSend.hpp +++ b/src/IRSend.hpp @@ -223,6 +223,9 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) { } else if (tProtocol == RC6) { sendRC6(tAddress, tCommand, aNumberOfRepeats, !tIsRepeat); // No toggle for repeats + } else if (tProtocol == RC6A) { + sendRC6A(tAddress, tCommand, aNumberOfRepeats, aIRSendData->extra, !tIsRepeat); + } else if (tProtocol == KASEIKYO_JVC) { sendKaseikyo_JVC(tAddress, tCommand, aNumberOfRepeats); @@ -270,7 +273,7 @@ size_t IRsend::write(IRData *aIRSendData, int_fast8_t aNumberOfRepeats) { } /** - * Simple version of write without support for MAGIQUEST and numberOfBits for SONY protocol + * Simple version of write without support for RC6A, MAGIQUEST and numberOfBits for SONY protocol * @param aNumberOfRepeats If aNumberOfRepeats < 0 then only a special repeat frame without leading and trailing space * will be sent by calling NECProtocolConstants.SpecialSendRepeatFunction(). */