mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
[Build] Add compatibility with C++20 (#2040)
* [Build] Add compatibility with C++20 * [Build] ESP32 builds both IDF 4.x and IDF 5.x * [Build] C++20 Use typedefs to switch compilation (volatile vs atomic where needed) * [Linter] Fix complaint about spaces :-| * [Linter] Fix more complaints about spaces :-| * [Build] esp32dev build restore standard espressif32 platform * [Build] C++20 Adjust typedefs and code to avoid deprecation warnings * [Build] esp32devIDF5x build restore Arduino 2.0.14 platform * [Build] esp32devIDF5x build enable Arduino 3.0.0 alpha1 platform by switching interrupts off/on instead of (missing) low-level IDF calls * [Build] Remove unneeded duplicate typedefs * [Linter] Fix complaint about comment line-length :-| * [Build] Add correct include to get `gpio_intr_enable` and `gpio_intr_disable`, thnx Jason2866! * Add comment why code was changed * [Lib] Add latest ESP32 fixes by @s-hadinger, add extra NULL safeguard, update Platform build * [IDF5] Update platform package to avoid python script issues long solved
This commit is contained in:
@@ -443,7 +443,7 @@ char Hostname[kHostnameLength + 1] = "ir_server"; // Default hostname.
|
||||
uint16_t *codeArray;
|
||||
uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number
|
||||
bool boot = true;
|
||||
volatile bool lockIr = false; // Primitive locking for gating the IR LED.
|
||||
atomic_bool lockIr = false; // Primitive locking for gating the IR LED.
|
||||
uint32_t sendReqCounter = 0;
|
||||
bool lastSendSucceeded = false; // Store the success status of the last send.
|
||||
uint32_t lastSendTime = 0;
|
||||
|
||||
@@ -18,5 +18,10 @@ board = nodemcuv2
|
||||
board = d1_mini
|
||||
|
||||
[env:esp32dev]
|
||||
platform = espressif32
|
||||
platform = espressif32 @ ^6.4.0
|
||||
board = esp32dev
|
||||
|
||||
# Experimental IDF 5.x support
|
||||
[env:esp32devIDF5x]
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.12.30/platform-espressif32.zip
|
||||
board = esp32dev
|
||||
|
||||
@@ -21,6 +21,12 @@ extern "C" {
|
||||
#include "IRremoteESP8266.h"
|
||||
#include "IRutils.h"
|
||||
|
||||
#if defined(ESP32)
|
||||
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 3) )
|
||||
#include <driver/gpio.h>
|
||||
#endif // ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||
#endif
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
#undef ICACHE_RAM_ATTR
|
||||
#define ICACHE_RAM_ATTR
|
||||
@@ -148,7 +154,7 @@ namespace _IRrecv { // Namespace extension
|
||||
#if defined(ESP32)
|
||||
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
#endif // ESP32
|
||||
volatile irparams_t params;
|
||||
atomic_irparams_t params;
|
||||
irparams_t *params_save; // A copy of the interrupt state while decoding.
|
||||
} // namespace _IRrecv
|
||||
|
||||
@@ -219,7 +225,7 @@ static void USE_IRAM_ATTR gpio_intr() {
|
||||
else
|
||||
params.rawbuf[rawlen] = (now - start) / kRawTick;
|
||||
}
|
||||
params.rawlen++;
|
||||
params.rawlen = params.rawlen + 1; // C++20 fix
|
||||
|
||||
start = now;
|
||||
|
||||
@@ -342,9 +348,6 @@ IRrecv::IRrecv(const uint16_t recvpin, const uint16_t bufsize,
|
||||
/// timers or interrupts used.
|
||||
IRrecv::~IRrecv(void) {
|
||||
disableIRIn();
|
||||
#if defined(ESP32)
|
||||
if (timer != NULL) timerEnd(timer); // Cleanup the ESP32 timeout timer.
|
||||
#endif // ESP32
|
||||
delete[] params.rawbuf;
|
||||
if (params_save != NULL) {
|
||||
delete[] params_save->rawbuf;
|
||||
@@ -425,6 +428,7 @@ void IRrecv::disableIRIn(void) {
|
||||
timerAlarmDisable(timer);
|
||||
timerDetachInterrupt(timer);
|
||||
timerEnd(timer);
|
||||
timer = NULL; // Cleanup the ESP32 timeout timer.
|
||||
#endif // ESP32
|
||||
detachInterrupt(params.recvpin);
|
||||
#endif // UNIT_TEST
|
||||
@@ -467,7 +471,7 @@ void IRrecv::resume(void) {
|
||||
/// i.e. In kStopState.
|
||||
/// @param[in] src Pointer to an irparams_t structure to copy from.
|
||||
/// @param[out] dst Pointer to an irparams_t structure to copy to.
|
||||
void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) {
|
||||
void IRrecv::copyIrParams(atomic_irparams_t *src, irparams_t *dst) {
|
||||
// Typecast src and dst addresses to (char *)
|
||||
char *csrc = (char *)src; // NOLINT(readability/casting)
|
||||
char *cdst = (char *)dst; // NOLINT(readability/casting)
|
||||
@@ -532,8 +536,8 @@ void IRrecv::crudeNoiseFilter(decode_results *results, const uint16_t floor) {
|
||||
for (uint16_t i = offset + 2; i <= results->rawlen && i < kBufSize; i++)
|
||||
results->rawbuf[i - 2] = results->rawbuf[i];
|
||||
if (offset > 1) { // There is a previous pair we can add to.
|
||||
// Merge this pair into into the previous space.
|
||||
results->rawbuf[offset - 1] += addition;
|
||||
// Merge this pair into into the previous space. // C++20 fix applied
|
||||
results->rawbuf[offset - 1] = results->rawbuf[offset - 1] + addition;
|
||||
}
|
||||
results->rawlen -= 2; // Adjust the length.
|
||||
} else {
|
||||
@@ -1489,7 +1493,7 @@ bool IRrecv::decodeHash(decode_results *results) {
|
||||
/// @return A match_result_t structure containing the success (or not), the
|
||||
/// data value, and how many buffer entries were used.
|
||||
match_result_t IRrecv::matchData(
|
||||
volatile uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark,
|
||||
atomic_uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark,
|
||||
const uint32_t onespace, const uint16_t zeromark, const uint32_t zerospace,
|
||||
const uint8_t tolerance, const int16_t excess, const bool MSBfirst,
|
||||
const bool expectlastspace) {
|
||||
@@ -1549,7 +1553,7 @@ match_result_t IRrecv::matchData(
|
||||
/// true is Most Significant Bit First Order, false is Least Significant First
|
||||
/// @param[in] expectlastspace Do we expect a space at the end of the message?
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
uint16_t IRrecv::matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
uint16_t IRrecv::matchBytes(atomic_uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
const uint16_t remaining, const uint16_t nbytes,
|
||||
const uint16_t onemark, const uint32_t onespace,
|
||||
const uint16_t zeromark, const uint32_t zerospace,
|
||||
@@ -1601,7 +1605,7 @@ uint16_t IRrecv::matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
|
||||
/// true is Most Significant Bit First Order, false is Least Significant First
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
|
||||
uint16_t IRrecv::_matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_bits_ptr,
|
||||
uint8_t *result_bytes_ptr,
|
||||
const bool use_bits,
|
||||
@@ -1703,7 +1707,7 @@ uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
|
||||
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
|
||||
/// true is Most Significant Bit First Order, false is Least Significant First
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
|
||||
uint16_t IRrecv::matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -1750,7 +1754,7 @@ uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
|
||||
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
|
||||
/// true is Most Significant Bit First Order, false is Least Significant First
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
|
||||
uint16_t IRrecv::matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint8_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -1797,7 +1801,7 @@ uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
/// @note Parameters one + zero add up to the total time for a bit.
|
||||
/// e.g. mark(one) + space(zero) is a `1`, mark(zero) + space(one) is a `0`.
|
||||
uint16_t IRrecv::matchGenericConstBitTime(volatile uint16_t *data_ptr,
|
||||
uint16_t IRrecv::matchGenericConstBitTime(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -1884,7 +1888,7 @@ uint16_t IRrecv::matchGenericConstBitTime(volatile uint16_t *data_ptr,
|
||||
/// @return If successful, how many buffer entries were used. Otherwise 0.
|
||||
/// @see https://en.wikipedia.org/wiki/Manchester_code
|
||||
/// @see http://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf
|
||||
uint16_t IRrecv::matchManchester(volatile const uint16_t *data_ptr,
|
||||
uint16_t IRrecv::matchManchester(atomic_const_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -1991,7 +1995,7 @@ uint16_t IRrecv::matchManchester(volatile const uint16_t *data_ptr,
|
||||
/// @see https://en.wikipedia.org/wiki/Manchester_code
|
||||
/// @see http://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf
|
||||
/// @todo Clean up and optimise this. It is just "get it working code" atm.
|
||||
uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr,
|
||||
uint16_t IRrecv::matchManchesterData(atomic_const_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -2112,7 +2116,7 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr,
|
||||
|
||||
#if UNIT_TEST
|
||||
/// Unit test helper to get access to the params structure.
|
||||
volatile irparams_t *IRrecv::_getParamsPtr(void) {
|
||||
atomic_irparams_t *IRrecv::_getParamsPtr(void) {
|
||||
return ¶ms;
|
||||
}
|
||||
#endif // UNIT_TEST
|
||||
|
||||
25
src/IRrecv.h
25
src/IRrecv.h
@@ -86,6 +86,8 @@ typedef struct {
|
||||
uint8_t timeout; // Nr. of milliSeconds before we give up.
|
||||
} irparams_t;
|
||||
|
||||
typedef volatile irparams_t atomic_irparams_t;
|
||||
|
||||
/// Results from a data match
|
||||
typedef struct {
|
||||
bool success; // Was the match successful?
|
||||
@@ -111,7 +113,7 @@ class decode_results {
|
||||
uint8_t state[kStateSizeMax]; // Multi-byte results.
|
||||
};
|
||||
uint16_t bits; // Number of bits in decoded value
|
||||
volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks
|
||||
atomic_uint16_t *rawbuf; // Raw intervals in .5 us ticks
|
||||
uint16_t rawlen; // Number of records in rawbuf.
|
||||
bool overflow;
|
||||
bool repeat; // Is the result a repeat code?
|
||||
@@ -171,11 +173,11 @@ class IRrecv {
|
||||
uint16_t _unknown_threshold;
|
||||
#endif
|
||||
#ifdef UNIT_TEST
|
||||
volatile irparams_t *_getParamsPtr(void);
|
||||
atomic_irparams_t *_getParamsPtr(void);
|
||||
#endif // UNIT_TEST
|
||||
// These are called by decode
|
||||
uint8_t _validTolerance(const uint8_t percentage);
|
||||
void copyIrParams(volatile irparams_t *src, irparams_t *dst);
|
||||
void copyIrParams(atomic_irparams_t *src, irparams_t *dst);
|
||||
uint16_t compare(const uint16_t oldval, const uint16_t newval);
|
||||
uint32_t ticksLow(const uint32_t usecs,
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
@@ -186,7 +188,7 @@ class IRrecv {
|
||||
bool matchAtLeast(const uint32_t measured, const uint32_t desired,
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const uint16_t delta = 0);
|
||||
uint16_t _matchGeneric(volatile uint16_t *data_ptr,
|
||||
uint16_t _matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_bits_ptr,
|
||||
uint8_t *result_ptr,
|
||||
const bool use_bits,
|
||||
@@ -204,14 +206,14 @@ class IRrecv {
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true);
|
||||
match_result_t matchData(volatile uint16_t *data_ptr, const uint16_t nbits,
|
||||
match_result_t matchData(atomic_uint16_t *data_ptr, const uint16_t nbits,
|
||||
const uint16_t onemark, const uint32_t onespace,
|
||||
const uint16_t zeromark, const uint32_t zerospace,
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true,
|
||||
const bool expectlastspace = true);
|
||||
uint16_t matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
uint16_t matchBytes(atomic_uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
const uint16_t remaining, const uint16_t nbytes,
|
||||
const uint16_t onemark, const uint32_t onespace,
|
||||
const uint16_t zeromark, const uint32_t zerospace,
|
||||
@@ -219,7 +221,7 @@ class IRrecv {
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true,
|
||||
const bool expectlastspace = true);
|
||||
uint16_t matchGeneric(volatile uint16_t *data_ptr,
|
||||
uint16_t matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining, const uint16_t nbits,
|
||||
const uint16_t hdrmark, const uint32_t hdrspace,
|
||||
@@ -230,7 +232,8 @@ class IRrecv {
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true);
|
||||
uint16_t matchGeneric(volatile uint16_t *data_ptr, uint8_t *result_ptr,
|
||||
uint16_t matchGeneric(atomic_uint16_t *data_ptr,
|
||||
uint8_t *result_ptr,
|
||||
const uint16_t remaining, const uint16_t nbits,
|
||||
const uint16_t hdrmark, const uint32_t hdrspace,
|
||||
const uint16_t onemark, const uint32_t onespace,
|
||||
@@ -241,7 +244,7 @@ class IRrecv {
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true);
|
||||
uint16_t matchGenericConstBitTime(volatile uint16_t *data_ptr,
|
||||
uint16_t matchGenericConstBitTime(atomic_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -255,7 +258,7 @@ class IRrecv {
|
||||
const uint8_t tolerance = kUseDefTol,
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true);
|
||||
uint16_t matchManchesterData(volatile const uint16_t *data_ptr,
|
||||
uint16_t matchManchesterData(atomic_const_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
@@ -265,7 +268,7 @@ class IRrecv {
|
||||
const int16_t excess = kMarkExcess,
|
||||
const bool MSBfirst = true,
|
||||
const bool GEThomas = true);
|
||||
uint16_t matchManchester(volatile const uint16_t *data_ptr,
|
||||
uint16_t matchManchester(atomic_const_uint16_t *data_ptr,
|
||||
uint64_t *result_ptr,
|
||||
const uint16_t remaining,
|
||||
const uint16_t nbits,
|
||||
|
||||
@@ -51,6 +51,16 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#endif // UNIT_TEST
|
||||
#if __cplusplus >= 202002L
|
||||
#include <atomic>
|
||||
typedef std::atomic< bool > atomic_bool;
|
||||
typedef std::atomic<uint32_t> atomic_uint32_t;
|
||||
#else
|
||||
typedef volatile bool atomic_bool;
|
||||
typedef volatile uint32_t atomic_uint32_t;
|
||||
#endif
|
||||
typedef volatile uint16_t atomic_uint16_t;
|
||||
typedef volatile const uint16_t atomic_const_uint16_t;
|
||||
|
||||
// Library Version Information
|
||||
// Major version number (X.x.x)
|
||||
|
||||
@@ -48,7 +48,7 @@ TEST(TestIRrecv, DecodeHeapOverflow) {
|
||||
IRrecv irrecv(1);
|
||||
irrecv.enableIRIn();
|
||||
ASSERT_EQ(kRawBuf, irrecv.getBufSize());
|
||||
volatile irparams_t *params_ptr = irrecv._getParamsPtr();
|
||||
atomic_irparams_t *params_ptr = irrecv._getParamsPtr();
|
||||
// replace the buffer with a slightly bigger one to see if we go past the end
|
||||
// accidentally.
|
||||
params_ptr->rawbuf = new uint16_t[kRawBuf + 10];
|
||||
|
||||
Reference in New Issue
Block a user