diff --git a/src/IRrecv.cpp b/src/IRrecv.cpp index 316dfc149..535578810 100644 --- a/src/IRrecv.cpp +++ b/src/IRrecv.cpp @@ -56,20 +56,24 @@ static ETSTimer timer; } // namespace _IRrecv #endif // ESP8266 #if defined(ESP32) +#if ( defined(ESP_ARDUINO_VERSION) && \ + (ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)) ) +#define _ESP32_ARDUINO_CORE_V3PLUS +#endif // ESP_ARDUINO_VERSION >= 3 // We need a horrible timer hack for ESP32 Arduino framework < v2.0.0 -#if !defined(_ESP32_IRRECV_TIMER_HACK) +#if !defined(_ESP32_ARDUINO_CORE_V2PLUS) // Version check #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) // No need for the hack if we are running version >= 2.0.0 -#define _ESP32_IRRECV_TIMER_HACK false +#define _ESP32_ARDUINO_CORE_V2PLUS false #else // Version check // If no ESP_ARDUINO_VERSION_MAJOR is defined, or less than 2, then we are // using an old ESP32 core, so we need the hack. -#define _ESP32_IRRECV_TIMER_HACK true +#define _ESP32_ARDUINO_CORE_V2PLUS true #endif // Version check -#endif // !defined(_ESP32_IRRECV_TIMER_HACK) +#endif // !defined(_ESP32_ARDUINO_CORE_V2PLUS) -#if _ESP32_IRRECV_TIMER_HACK +#if _ESP32_ARDUINO_CORE_V2PLUS // Required structs/types from: // https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L28-L58 // These are needed to be able to directly manipulate the timer registers from @@ -131,10 +135,10 @@ typedef struct hw_timer_s { uint8_t timer; portMUX_TYPE lock; } hw_timer_t; -#endif // _ESP32_IRRECV_TIMER_HACK / End of Horrible Hack. +#endif // _ESP32_ARDUINO_CORE_V2PLUS / End of Horrible Hack. namespace _IRrecv { -static hw_timer_t * timer = NULL; +static hw_timer_t *timer = NULL; } // namespace _IRrecv #endif // ESP32 using _IRrecv::timer; @@ -225,26 +229,31 @@ static void USE_IRAM_ATTR gpio_intr() { #if defined(ESP32) // Reset the timeout. // -#if _ESP32_IRRECV_TIMER_HACK - // The following three lines of code are the equiv of: +#if _ESP32_ARDUINO_CORE_V2PLUS + // The following three lines of code are the equivalent of: // `timerWrite(timer, 0);` // We can't call that routine safely from inside an ISR as that procedure // is not stored in IRAM. Hence, we do it manually so that it's covered by // USE_IRAM_ATTR in this ISR. // @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1350 // @see https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L106-L110 - timer->dev->load_high = (uint32_t) 0; - timer->dev->load_low = (uint32_t) 0; + timer->dev->load_high = static_cast<uint32_t>(0); + timer->dev->load_low = static_cast<uint32_t>(0); timer->dev->reload = 1; // The next line is the same, but instead replaces: // `timerAlarmEnable(timer);` // @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1350 // @see https://github.com/espressif/arduino-esp32/blob/6b0114366baf986c155e8173ab7c22bc0c5fcedc/cores/esp32/esp32-hal-timer.c#L176-L178 timer->dev->config.alarm_en = 1; -#else // _ESP32_IRRECV_TIMER_HACK +#elif defined(_ESP32_ARDUINO_CORE_V3PLUS) + // For ESP32 core version 3.x, replace `timerAlarmEnable` + timerWrite(timer, 0); + uint64_t alarm_value = 50000; // Example value (50ms) + timerAlarm(timer, alarm_value, false, 0); +#else // !_ESP32_ARDUINO_CORE_V3PLUS timerWrite(timer, 0); timerAlarmEnable(timer); -#endif // _ESP32_IRRECV_TIMER_HACK +#endif // _ESP32_ARDUINO_CORE_V2PLUS #endif // ESP32 } #endif // UNIT_TEST @@ -358,8 +367,15 @@ void IRrecv::enableIRIn(const bool pullup) { } #if defined(ESP32) // Initialise the ESP32 timer. +#if defined(_ESP32_ARDUINO_CORE_V3PLUS) + // Use newer timerBegin signature for ESP32 core version 3.x + timer = timerBegin(1000000); // Initialize with 1MHz (1us per tick) +#else // _ESP32_ARDUINO_CORE_V3PLUS // 80MHz / 80 = 1 uSec granularity. timer = timerBegin(_timer_num, 80, true); +#endif // _ESP32_ARDUINO_CORE_V3PLUS + + // Ensure the timer is successfully initialized #ifdef DEBUG if (timer == NULL) { DPRINT("FATAL: Unable enable system timer: "); @@ -367,12 +383,17 @@ void IRrecv::enableIRIn(const bool pullup) { } #endif // DEBUG assert(timer != NULL); // Check we actually got the timer. - // Set the timer so it only fires once, and set it's trigger in uSeconds. + // Set the timer so it only fires once, and set its trigger in microseconds. +#if defined(_ESP32_ARDUINO_CORE_V3PLUS) + timerWrite(timer, 0); // Reset the timer for ESP32 core version 3.x + timerAttachInterrupt(timer, &read_timeout); +#else // _ESP32_ARDUINO_CORE_V3PLUS timerAlarmWrite(timer, MS_TO_USEC(params.timeout), ONCE); // Note: Interrupt needs to be attached before it can be enabled or disabled. // Note: EDGE (true) is not supported, use LEVEL (false). Ref: #1713 // See: https://github.com/espressif/arduino-esp32/blob/caef4006af491130136b219c1205bdcf8f08bf2b/cores/esp32/esp32-hal-timer.c#L224-L227 timerAttachInterrupt(timer, &read_timeout, false); +#endif // _ESP32_ARDUINO_CORE_V3PLUS #endif // ESP32 // Initialise state machine variables @@ -396,8 +417,11 @@ void IRrecv::disableIRIn(void) { #ifndef UNIT_TEST #if defined(ESP8266) os_timer_disarm(&timer); -#endif // ESP8266 -#if defined(ESP32) +#elif defined(_ESP32_ARDUINO_CORE_V3PLUS) + timerWrite(timer, 0); // Reset the timer + timerDetachInterrupt(timer); + timerEnd(timer); +#elif defined(ESP32) timerAlarmDisable(timer); timerDetachInterrupt(timer); timerEnd(timer); @@ -426,7 +450,13 @@ void IRrecv::resume(void) { params.rawlen = 0; params.overflow = false; #if defined(ESP32) + // Check for ESP32 core version and handle timer functions differently +#if defined(_ESP32_ARDUINO_CORE_V3PLUS) + timerWrite(timer, 0); // Reset the timer (no need for timerAlarmDisable) +#else // _ESP32_ARDUINO_CORE_V3PLUS timerAlarmDisable(timer); +#endif // _ESP32_ARDUINO_CORE_V3PLUS + // Re-enable GPIO interrupt in both versions gpio_intr_enable((gpio_num_t)params.recvpin); #endif // ESP32 }