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 01/27] 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 0b129eb5..3868598f 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 02/27] 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 349ccec1..40c04046 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 0ee428a6..4dcaaedb 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 ec69d2d6..af477fc2 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 61f5d407..68f49f2d 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 3868598f..c8bf924c 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 03/27] 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 4dcaaedb..13260d97 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 af477fc2..5234a975 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 ed9e18cd..c70463de 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 7a56be84..358c3118 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 28f5c252..a4a584f0 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 bad39fea..d8c440d4 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 68f49f2d..b2e933e2 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 fc204e0c..46829905 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 4f89fa2c..c01a67ab 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 19c47bc4..39b3414e 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 c8bf924c..9e395a73 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 04/27] 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 13260d97..8280c069 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 05/27] 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 b2e933e2..44bbbae8 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 470c6479..5669b1de 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 06bc15e7..b7b31d27 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 06/27] 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 44bbbae8..ec7963d4 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 46829905..716d4ebc 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 1bb8eb50..043ae715 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 fed25bcc..1885f3bf 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 07/27] 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 17d84e08..1766e7c3 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 eae4a259..cda754b2 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 e235679e..e42b826e 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 668bb9a1..d4dd23f3 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 9e395a73..acb1b97c 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 08/27] 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 358c3118..48edd73a 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 c644f3e4..5a738da3 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 37d57d93..14573c78 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 cce8f42e..aac41eb2 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 97611b08..ff83b762 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 ec7963d4..1fb0ec6c 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 5669b1de..66813366 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 acb1b97c..a670f55d 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 09/27] 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 8280c069..57c58c96 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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 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 10/27] 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 57c58c96..1694220e 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 5234a975..50d3d874 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 48edd73a..99468db8 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 8f58e31c..d0451baa 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 5a738da3..36232640 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 aac41eb2..af464aa5 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 e96beb25..99acf3f2 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 96c2bffe..7def9abb 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 7a2bebdd..2a903bfe 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 e8c7a554..5f724c45 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 1fb0ec6c..380563b0 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 716d4ebc..7a35ffa1 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 2cc8dd43..424f52c8 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 a670f55d..aaf2ed96 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 11/27] 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 657f0687..43f3d5d7 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 12/27] 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 c6dbb9b0..1ca9d9f2 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 1694220e..4520ffc7 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 50d3d874..3ba38d7e 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 99468db8..d2cf21b9 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 36232640..03cdfab9 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 1766e7c3..b58a2945 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 14573c78..2dad3f4d 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 ff83b762..0e68965a 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 380563b0..d144733f 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 7a35ffa1..185f2fc3 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 39b3414e..e6515859 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 043ae715..a36a71f3 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 aaf2ed96..92c162e4 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 13/27] 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 1ca9d9f2..ab187e15 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 4520ffc7..c0e416ec 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 73030b47..ebf19026 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 d2cf21b9..b0e6abb1 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 36d79a6f..74d0c225 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 2dad3f4d..11b67735 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 b58a2945..8e4f5a60 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 2dad3f4d..11b67735 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 92c162e4..c2d555d8 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 14/27] Documentation --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c0e416ec..74f26812 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 15/27] 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 ab187e15..ba2dd15a 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 74f26812..d7af27a7 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 3ba38d7e..a62ab730 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 11b67735..9c5e9772 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 e6515859..85481b46 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 c2d555d8..6e708a61 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 16/27] 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 a62ab730..e3e90756 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 c0efd284..01245b13 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 9c5e9772..5e932829 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 11b67735..5e932829 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 85481b46..d32d023c 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 17/27] 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 cc9b32a1..00cc577e 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 e3e90756..b759322a 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 346b13b3..0ea2e73a 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 b0e6abb1..1ee81fdb 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 01245b13..ab732bcd 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 03cdfab9..5049e4bf 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 d4893f03..e935d00c 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 d8c440d4..a81d33f5 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 af464aa5..dfc0fb59 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 cda754b2..dbfb3f3e 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 185f2fc3..983964e6 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 f2214114..ba95babf 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 18/27] 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 00cc577e..d8727408 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 ebf19026..9cf096bc 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 c70463de..7a115c45 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 701103a1..5901c6a9 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 fda2a2c5..6df3321a 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 3ec197ad..d40c69ad 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 31d03766..25d0f09d 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 a5bcae2b..a468d026 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 ee4dc751..dad106fd 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 c0d9da01..146e34c1 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 159dad61..f9b3a2b0 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 d0451baa..dc235778 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 a4a584f0..e11a0875 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 9e99353d..9b80ab7e 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 a7eafb3d..5046b96c 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 90511f28..a92e45e2 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 8e184751..5b03a643 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 74d0c225..b4ca0ba6 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 8e4f5a60..91819446 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 a857203f..a126d642 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 d73b3748..55305363 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 7a1fb343..4af49883 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 5f724c45..c14c93a7 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 d144733f..2c2e6bd8 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 66813366..3b25c0d8 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 65a1fe18..86f308ac 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 c8ec9b7a..8035a61c 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 ba95babf..bca43f41 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 aa2d4ed2..4ce2c0fc 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 f9ea167c..bd5518b8 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 614cc00c..39e8b1dd 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 fe61f63e..02303014 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 52df1dbd..812b9605 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 291f8086..28d40c40 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 b02931cc..62b9e6ac 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 b7b31d27..620829ed 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 424f52c8..35506699 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 eaa6e921..6856ec4a 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 59b7a8f7..3a06948a 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 19/27] 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 d7af27a7..e461a1ac 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 c4062178..33c2bbfc 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 9cf096bc..8d0e5e79 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 5901c6a9..a8006400 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 a81d33f5..b31b4657 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 935f913e..adfe8467 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 0e68965a..0db0c02f 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 2c2e6bd8..cb3c5525 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 3b25c0d8..b9a4b786 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 983964e6..dbf140a0 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 d32d023c..97b7b61f 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 a36a71f3..f745081a 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 8035a61c..0843331d 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 bca43f41..0f64a0ab 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 bd5518b8..e5cee6ea 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 39e8b1dd..3c151679 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 02303014..01ce36c9 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 1885f3bf..410bf800 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 28d40c40..e16f8442 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 62b9e6ac..eb3d5298 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 cc5291b0..e6b24b87 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 6856ec4a..2ca504da 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 3a06948a..af9e6bc5 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 9855f51a..82bad807 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 6e708a61..872c4edd 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 20/27] 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 e461a1ac..d869ef3f 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 97b7b61f..7d4f0b11 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 21/27] Documentation --- README.md | 32 ++++++++++++++++++-------------- src/IRremote.h | 13 +++++++------ 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d869ef3f..97216d84 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 3af3f582..997ab371 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 22/27] 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 97216d84..aa5f8248 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 7a115c45..36c5648b 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 8a315e9c..f2f8cef4 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 d40c69ad..50bea009 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 a468d026..ca2a9b18 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 dad106fd..a5f3adbb 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 146e34c1..78a999ad 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 1ee81fdb..a3b2ecb4 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 dc235778..b0101062 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 b4ca0ba6..6d4d40a6 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 a126d642..5489dbc8 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 997ab371..3cc42969 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 23/27] 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 b759322a..c1514191 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 f2f8cef4..ef95f8fe 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 2fa648a7..73e8c5f6 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 a5f3adbb..591579d8 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 78a999ad..d096a459 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 a3b2ecb4..f66a10a7 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 dfc0fb59..e66d4fcb 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 99acf3f2..4063d890 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 2a903bfe..6b257dbd 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 c14c93a7..bbe4cc37 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 cb3c5525..dfce9427 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 dbf140a0..517c059e 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 c01a67ab..ccc9ba41 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 4ce2c0fc..bea84676 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 24/27] 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 ba2dd15a..60053509 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 aa5f8248..256003fc 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 c1514191..4372d417 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 00000000..33566bcb --- /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 55305363..c6d97d62 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 6b257dbd..2d765476 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 bbe4cc37..9153be56 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 517c059e..10a12244 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 25/27] 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 d096a459..a932e91a 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 5049e4bf..724963f6 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 e66d4fcb..fe996107 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 dfce9427..d5f4e78c 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 b9a4b786..5d7f0087 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 10a12244..02023a8d 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 7d4f0b11..4b2e8959 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 f745081a..faeaa5af 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 0843331d..336d886f 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 0f64a0ab..bfbe45ca 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 e5cee6ea..e01f9829 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 3c151679..90e7ed66 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 01ce36c9..9abce660 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 812b9605..ad35f812 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 410bf800..156bf743 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 e16f8442..c14e5307 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 eb3d5298..5bf750fe 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 e6b24b87..20e4cc62 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 2ca504da..8abc2fad 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 af9e6bc5..bcb9eb9d 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 82bad807..ce1dab06 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 26/27] 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 60053509..93aee142 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 4372d417..0ab56fa1 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 724963f6..c918aa3a 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 6d4d40a6..95eaee8c 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 fe996107..afdbf4bc 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 dbfb3f3e..c0666baa 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 e42b826e..40e043e2 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 9153be56..bed8fa7a 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 d5f4e78c..ab4095f6 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 5d7f0087..365c17c0 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 d4dd23f3..acbafa22 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 3cc42969..73cae038 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 43f3d5d7..826e8044 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 4b2e8959..c0d29661 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 90e7ed66..ef69a598 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 c14e5307..ccd214f8 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 620829ed..5fbad18c 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 35506699..b8eebb57 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 8abc2fad..976e8807 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 27/27] 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 256003fc..d630db6e 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 f66a10a7..e7aa1eb7 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 5e932829..b13414f5 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 ab4095f6..1c6ab4fb 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 365c17c0..f6c158df 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 826e8044..fdeeb835 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 ccc9ba41..8e29871e 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 c0d29661..af66d3c8 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 86f308ac..be0d07ef 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 } /** @}*/