Skip to content

Commit 95b87cc

Browse files
authored
[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
1 parent f66374d commit 95b87cc

File tree

6 files changed

+53
-31
lines changed

6 files changed

+53
-31
lines changed

examples/IRMQTTServer/IRMQTTServer.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ char Hostname[kHostnameLength + 1] = "ir_server"; // Default hostname.
443443
uint16_t *codeArray;
444444
uint32_t lastReconnectAttempt = 0; // MQTT last attempt reconnection number
445445
bool boot = true;
446-
volatile bool lockIr = false; // Primitive locking for gating the IR LED.
446+
atomic_bool lockIr = false; // Primitive locking for gating the IR LED.
447447
uint32_t sendReqCounter = 0;
448448
bool lastSendSucceeded = false; // Store the success status of the last send.
449449
uint32_t lastSendTime = 0;

platformio.ini

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ board = nodemcuv2
1818
board = d1_mini
1919

2020
[env:esp32dev]
21-
platform = espressif32
21+
platform = espressif32 @ ^6.4.0
2222
board = esp32dev
23+
24+
# Experimental IDF 5.x support
25+
[env:esp32devIDF5x]
26+
platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.12.30/platform-espressif32.zip
27+
board = esp32dev

src/IRrecv.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ extern "C" {
2121
#include "IRremoteESP8266.h"
2222
#include "IRutils.h"
2323

24+
#if defined(ESP32)
25+
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 3) )
26+
#include <driver/gpio.h>
27+
#endif // ESP_ARDUINO_VERSION_MAJOR >= 3
28+
#endif
29+
2430
#ifdef UNIT_TEST
2531
#undef ICACHE_RAM_ATTR
2632
#define ICACHE_RAM_ATTR
@@ -148,7 +154,7 @@ namespace _IRrecv { // Namespace extension
148154
#if defined(ESP32)
149155
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
150156
#endif // ESP32
151-
volatile irparams_t params;
157+
atomic_irparams_t params;
152158
irparams_t *params_save; // A copy of the interrupt state while decoding.
153159
} // namespace _IRrecv
154160

@@ -219,7 +225,7 @@ static void USE_IRAM_ATTR gpio_intr() {
219225
else
220226
params.rawbuf[rawlen] = (now - start) / kRawTick;
221227
}
222-
params.rawlen++;
228+
params.rawlen = params.rawlen + 1; // C++20 fix
223229

224230
start = now;
225231

@@ -342,9 +348,6 @@ IRrecv::IRrecv(const uint16_t recvpin, const uint16_t bufsize,
342348
/// timers or interrupts used.
343349
IRrecv::~IRrecv(void) {
344350
disableIRIn();
345-
#if defined(ESP32)
346-
if (timer != NULL) timerEnd(timer); // Cleanup the ESP32 timeout timer.
347-
#endif // ESP32
348351
delete[] params.rawbuf;
349352
if (params_save != NULL) {
350353
delete[] params_save->rawbuf;
@@ -425,6 +428,7 @@ void IRrecv::disableIRIn(void) {
425428
timerAlarmDisable(timer);
426429
timerDetachInterrupt(timer);
427430
timerEnd(timer);
431+
timer = NULL; // Cleanup the ESP32 timeout timer.
428432
#endif // ESP32
429433
detachInterrupt(params.recvpin);
430434
#endif // UNIT_TEST
@@ -467,7 +471,7 @@ void IRrecv::resume(void) {
467471
/// i.e. In kStopState.
468472
/// @param[in] src Pointer to an irparams_t structure to copy from.
469473
/// @param[out] dst Pointer to an irparams_t structure to copy to.
470-
void IRrecv::copyIrParams(volatile irparams_t *src, irparams_t *dst) {
474+
void IRrecv::copyIrParams(atomic_irparams_t *src, irparams_t *dst) {
471475
// Typecast src and dst addresses to (char *)
472476
char *csrc = (char *)src; // NOLINT(readability/casting)
473477
char *cdst = (char *)dst; // NOLINT(readability/casting)
@@ -532,8 +536,8 @@ void IRrecv::crudeNoiseFilter(decode_results *results, const uint16_t floor) {
532536
for (uint16_t i = offset + 2; i <= results->rawlen && i < kBufSize; i++)
533537
results->rawbuf[i - 2] = results->rawbuf[i];
534538
if (offset > 1) { // There is a previous pair we can add to.
535-
// Merge this pair into into the previous space.
536-
results->rawbuf[offset - 1] += addition;
539+
// Merge this pair into into the previous space. // C++20 fix applied
540+
results->rawbuf[offset - 1] = results->rawbuf[offset - 1] + addition;
537541
}
538542
results->rawlen -= 2; // Adjust the length.
539543
} else {
@@ -1489,7 +1493,7 @@ bool IRrecv::decodeHash(decode_results *results) {
14891493
/// @return A match_result_t structure containing the success (or not), the
14901494
/// data value, and how many buffer entries were used.
14911495
match_result_t IRrecv::matchData(
1492-
volatile uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark,
1496+
atomic_uint16_t *data_ptr, const uint16_t nbits, const uint16_t onemark,
14931497
const uint32_t onespace, const uint16_t zeromark, const uint32_t zerospace,
14941498
const uint8_t tolerance, const int16_t excess, const bool MSBfirst,
14951499
const bool expectlastspace) {
@@ -1549,7 +1553,7 @@ match_result_t IRrecv::matchData(
15491553
/// true is Most Significant Bit First Order, false is Least Significant First
15501554
/// @param[in] expectlastspace Do we expect a space at the end of the message?
15511555
/// @return If successful, how many buffer entries were used. Otherwise 0.
1552-
uint16_t IRrecv::matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
1556+
uint16_t IRrecv::matchBytes(atomic_uint16_t *data_ptr, uint8_t *result_ptr,
15531557
const uint16_t remaining, const uint16_t nbytes,
15541558
const uint16_t onemark, const uint32_t onespace,
15551559
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,
16011605
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
16021606
/// true is Most Significant Bit First Order, false is Least Significant First
16031607
/// @return If successful, how many buffer entries were used. Otherwise 0.
1604-
uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
1608+
uint16_t IRrecv::_matchGeneric(atomic_uint16_t *data_ptr,
16051609
uint64_t *result_bits_ptr,
16061610
uint8_t *result_bytes_ptr,
16071611
const bool use_bits,
@@ -1703,7 +1707,7 @@ uint16_t IRrecv::_matchGeneric(volatile uint16_t *data_ptr,
17031707
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
17041708
/// true is Most Significant Bit First Order, false is Least Significant First
17051709
/// @return If successful, how many buffer entries were used. Otherwise 0.
1706-
uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
1710+
uint16_t IRrecv::matchGeneric(atomic_uint16_t *data_ptr,
17071711
uint64_t *result_ptr,
17081712
const uint16_t remaining,
17091713
const uint16_t nbits,
@@ -1750,7 +1754,7 @@ uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
17501754
/// @param[in] MSBfirst Bit order to save the data in. (Def: true)
17511755
/// true is Most Significant Bit First Order, false is Least Significant First
17521756
/// @return If successful, how many buffer entries were used. Otherwise 0.
1753-
uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
1757+
uint16_t IRrecv::matchGeneric(atomic_uint16_t *data_ptr,
17541758
uint8_t *result_ptr,
17551759
const uint16_t remaining,
17561760
const uint16_t nbits,
@@ -1797,7 +1801,7 @@ uint16_t IRrecv::matchGeneric(volatile uint16_t *data_ptr,
17971801
/// @return If successful, how many buffer entries were used. Otherwise 0.
17981802
/// @note Parameters one + zero add up to the total time for a bit.
17991803
/// e.g. mark(one) + space(zero) is a `1`, mark(zero) + space(one) is a `0`.
1800-
uint16_t IRrecv::matchGenericConstBitTime(volatile uint16_t *data_ptr,
1804+
uint16_t IRrecv::matchGenericConstBitTime(atomic_uint16_t *data_ptr,
18011805
uint64_t *result_ptr,
18021806
const uint16_t remaining,
18031807
const uint16_t nbits,
@@ -1884,7 +1888,7 @@ uint16_t IRrecv::matchGenericConstBitTime(volatile uint16_t *data_ptr,
18841888
/// @return If successful, how many buffer entries were used. Otherwise 0.
18851889
/// @see https://en.wikipedia.org/wiki/Manchester_code
18861890
/// @see http://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf
1887-
uint16_t IRrecv::matchManchester(volatile const uint16_t *data_ptr,
1891+
uint16_t IRrecv::matchManchester(atomic_const_uint16_t *data_ptr,
18881892
uint64_t *result_ptr,
18891893
const uint16_t remaining,
18901894
const uint16_t nbits,
@@ -1991,7 +1995,7 @@ uint16_t IRrecv::matchManchester(volatile const uint16_t *data_ptr,
19911995
/// @see https://en.wikipedia.org/wiki/Manchester_code
19921996
/// @see http://ww1.microchip.com/downloads/en/AppNotes/Atmel-9164-Manchester-Coding-Basics_Application-Note.pdf
19931997
/// @todo Clean up and optimise this. It is just "get it working code" atm.
1994-
uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr,
1998+
uint16_t IRrecv::matchManchesterData(atomic_const_uint16_t *data_ptr,
19951999
uint64_t *result_ptr,
19962000
const uint16_t remaining,
19972001
const uint16_t nbits,
@@ -2112,7 +2116,7 @@ uint16_t IRrecv::matchManchesterData(volatile const uint16_t *data_ptr,
21122116

21132117
#if UNIT_TEST
21142118
/// Unit test helper to get access to the params structure.
2115-
volatile irparams_t *IRrecv::_getParamsPtr(void) {
2119+
atomic_irparams_t *IRrecv::_getParamsPtr(void) {
21162120
return &params;
21172121
}
21182122
#endif // UNIT_TEST

src/IRrecv.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ typedef struct {
8686
uint8_t timeout; // Nr. of milliSeconds before we give up.
8787
} irparams_t;
8888

89+
typedef volatile irparams_t atomic_irparams_t;
90+
8991
/// Results from a data match
9092
typedef struct {
9193
bool success; // Was the match successful?
@@ -111,7 +113,7 @@ class decode_results {
111113
uint8_t state[kStateSizeMax]; // Multi-byte results.
112114
};
113115
uint16_t bits; // Number of bits in decoded value
114-
volatile uint16_t *rawbuf; // Raw intervals in .5 us ticks
116+
atomic_uint16_t *rawbuf; // Raw intervals in .5 us ticks
115117
uint16_t rawlen; // Number of records in rawbuf.
116118
bool overflow;
117119
bool repeat; // Is the result a repeat code?
@@ -171,11 +173,11 @@ class IRrecv {
171173
uint16_t _unknown_threshold;
172174
#endif
173175
#ifdef UNIT_TEST
174-
volatile irparams_t *_getParamsPtr(void);
176+
atomic_irparams_t *_getParamsPtr(void);
175177
#endif // UNIT_TEST
176178
// These are called by decode
177179
uint8_t _validTolerance(const uint8_t percentage);
178-
void copyIrParams(volatile irparams_t *src, irparams_t *dst);
180+
void copyIrParams(atomic_irparams_t *src, irparams_t *dst);
179181
uint16_t compare(const uint16_t oldval, const uint16_t newval);
180182
uint32_t ticksLow(const uint32_t usecs,
181183
const uint8_t tolerance = kUseDefTol,
@@ -186,7 +188,7 @@ class IRrecv {
186188
bool matchAtLeast(const uint32_t measured, const uint32_t desired,
187189
const uint8_t tolerance = kUseDefTol,
188190
const uint16_t delta = 0);
189-
uint16_t _matchGeneric(volatile uint16_t *data_ptr,
191+
uint16_t _matchGeneric(atomic_uint16_t *data_ptr,
190192
uint64_t *result_bits_ptr,
191193
uint8_t *result_ptr,
192194
const bool use_bits,
@@ -204,22 +206,22 @@ class IRrecv {
204206
const uint8_t tolerance = kUseDefTol,
205207
const int16_t excess = kMarkExcess,
206208
const bool MSBfirst = true);
207-
match_result_t matchData(volatile uint16_t *data_ptr, const uint16_t nbits,
209+
match_result_t matchData(atomic_uint16_t *data_ptr, const uint16_t nbits,
208210
const uint16_t onemark, const uint32_t onespace,
209211
const uint16_t zeromark, const uint32_t zerospace,
210212
const uint8_t tolerance = kUseDefTol,
211213
const int16_t excess = kMarkExcess,
212214
const bool MSBfirst = true,
213215
const bool expectlastspace = true);
214-
uint16_t matchBytes(volatile uint16_t *data_ptr, uint8_t *result_ptr,
216+
uint16_t matchBytes(atomic_uint16_t *data_ptr, uint8_t *result_ptr,
215217
const uint16_t remaining, const uint16_t nbytes,
216218
const uint16_t onemark, const uint32_t onespace,
217219
const uint16_t zeromark, const uint32_t zerospace,
218220
const uint8_t tolerance = kUseDefTol,
219221
const int16_t excess = kMarkExcess,
220222
const bool MSBfirst = true,
221223
const bool expectlastspace = true);
222-
uint16_t matchGeneric(volatile uint16_t *data_ptr,
224+
uint16_t matchGeneric(atomic_uint16_t *data_ptr,
223225
uint64_t *result_ptr,
224226
const uint16_t remaining, const uint16_t nbits,
225227
const uint16_t hdrmark, const uint32_t hdrspace,
@@ -230,7 +232,8 @@ class IRrecv {
230232
const uint8_t tolerance = kUseDefTol,
231233
const int16_t excess = kMarkExcess,
232234
const bool MSBfirst = true);
233-
uint16_t matchGeneric(volatile uint16_t *data_ptr, uint8_t *result_ptr,
235+
uint16_t matchGeneric(atomic_uint16_t *data_ptr,
236+
uint8_t *result_ptr,
234237
const uint16_t remaining, const uint16_t nbits,
235238
const uint16_t hdrmark, const uint32_t hdrspace,
236239
const uint16_t onemark, const uint32_t onespace,
@@ -241,7 +244,7 @@ class IRrecv {
241244
const uint8_t tolerance = kUseDefTol,
242245
const int16_t excess = kMarkExcess,
243246
const bool MSBfirst = true);
244-
uint16_t matchGenericConstBitTime(volatile uint16_t *data_ptr,
247+
uint16_t matchGenericConstBitTime(atomic_uint16_t *data_ptr,
245248
uint64_t *result_ptr,
246249
const uint16_t remaining,
247250
const uint16_t nbits,
@@ -255,7 +258,7 @@ class IRrecv {
255258
const uint8_t tolerance = kUseDefTol,
256259
const int16_t excess = kMarkExcess,
257260
const bool MSBfirst = true);
258-
uint16_t matchManchesterData(volatile const uint16_t *data_ptr,
261+
uint16_t matchManchesterData(atomic_const_uint16_t *data_ptr,
259262
uint64_t *result_ptr,
260263
const uint16_t remaining,
261264
const uint16_t nbits,
@@ -265,7 +268,7 @@ class IRrecv {
265268
const int16_t excess = kMarkExcess,
266269
const bool MSBfirst = true,
267270
const bool GEThomas = true);
268-
uint16_t matchManchester(volatile const uint16_t *data_ptr,
271+
uint16_t matchManchester(atomic_const_uint16_t *data_ptr,
269272
uint64_t *result_ptr,
270273
const uint16_t remaining,
271274
const uint16_t nbits,

src/IRremoteESP8266.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@
5151
#include <iostream>
5252
#include <string>
5353
#endif // UNIT_TEST
54+
#if __cplusplus >= 202002L
55+
#include <atomic>
56+
typedef std::atomic< bool > atomic_bool;
57+
typedef std::atomic<uint32_t> atomic_uint32_t;
58+
#else
59+
typedef volatile bool atomic_bool;
60+
typedef volatile uint32_t atomic_uint32_t;
61+
#endif
62+
typedef volatile uint16_t atomic_uint16_t;
63+
typedef volatile const uint16_t atomic_const_uint16_t;
5464

5565
// Library Version Information
5666
// Major version number (X.x.x)

test/IRrecv_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ TEST(TestIRrecv, DecodeHeapOverflow) {
4848
IRrecv irrecv(1);
4949
irrecv.enableIRIn();
5050
ASSERT_EQ(kRawBuf, irrecv.getBufSize());
51-
volatile irparams_t *params_ptr = irrecv._getParamsPtr();
51+
atomic_irparams_t *params_ptr = irrecv._getParamsPtr();
5252
// replace the buffer with a slightly bigger one to see if we go past the end
5353
// accidentally.
5454
params_ptr->rawbuf = new uint16_t[kRawBuf + 10];

0 commit comments

Comments
 (0)