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
 }