1 #if defined(PLATFORM_ESP32)
5 void (*hwTimer::callbackTick
)() = nullptr;
6 void (*hwTimer::callbackTock
)() = nullptr;
8 volatile bool hwTimer::running
= false;
9 volatile bool hwTimer::isTick
= false;
11 volatile uint32_t hwTimer::HWtimerInterval
= TimerIntervalUSDefault
;
12 volatile int32_t hwTimer::PhaseShift
= 0;
13 volatile int32_t hwTimer::FreqOffset
= 0;
15 // Internal implementation specific variables
16 static hw_timer_t
*timer
= NULL
;
17 static portMUX_TYPE isrMutex
= portMUX_INITIALIZER_UNLOCKED
;
19 #if defined(TARGET_RX)
20 #define HWTIMER_TICKS_PER_US 5
22 #define HWTIMER_TICKS_PER_US 1
25 void ICACHE_RAM_ATTR
hwTimer::init(void (*callbackTick
)(), void (*callbackTock
)())
30 hwTimer::callbackTick
= callbackTick
;
31 hwTimer::callbackTock
= callbackTock
;
32 timer
= timerBegin(0, (APB_CLK_FREQ
/ 1000000 / HWTIMER_TICKS_PER_US
), true);
33 timerAttachInterrupt(timer
, hwTimer::callback
, true);
34 DBGLN("hwTimer Init");
38 void ICACHE_RAM_ATTR
hwTimer::stop()
43 timerAlarmDisable(timer
);
44 DBGLN("hwTimer stop");
48 void ICACHE_RAM_ATTR
hwTimer::resume()
50 if (timer
&& !running
)
52 // The timer must be restarted so that the new timerAlarmWrite() period is set.
54 #if defined(TARGET_TX)
55 timerAlarmWrite(timer
, HWtimerInterval
, true);
57 // We want the timer to fire tock() ASAP after enabling
58 // tock() should always be the first event to maintain consistency
60 // When using EDGE triggered timer, enabling the timer causes an edge so the interrupt
61 // is fired immediately
62 // Unlike the 8266 timer, the ESP32 timer can be started without delay.
63 // It does not interrupt the currently running IsrCallback(), but triggers immediately once it has completed.
64 timerAlarmWrite(timer
, 0 * HWTIMER_TICKS_PER_US
, true);
67 timerAlarmEnable(timer
);
68 DBGLN("hwTimer resume");
72 void ICACHE_RAM_ATTR
hwTimer::updateInterval(uint32_t time
)
74 // timer should not be running when updateInterval() is called
75 HWtimerInterval
= time
* HWTIMER_TICKS_PER_US
;
78 DBGLN("hwTimer interval: %d", time
);
79 timerAlarmWrite(timer
, HWtimerInterval
, true);
83 void ICACHE_RAM_ATTR
hwTimer::phaseShift(int32_t newPhaseShift
)
85 int32_t minVal
= -(HWtimerInterval
>> 2);
86 int32_t maxVal
= (HWtimerInterval
>> 2);
88 // phase shift is in microseconds
89 PhaseShift
= constrain(newPhaseShift
, minVal
, maxVal
) * HWTIMER_TICKS_PER_US
;
92 void ICACHE_RAM_ATTR
hwTimer::callback(void)
96 portENTER_CRITICAL_ISR(&isrMutex
);
97 #if defined(TARGET_TX)
100 uint32_t NextInterval
= (HWtimerInterval
>> 1) + FreqOffset
;
103 timerAlarmWrite(timer
, NextInterval
, true);
104 hwTimer::callbackTick();
108 NextInterval
+= PhaseShift
;
109 timerAlarmWrite(timer
, NextInterval
, true);
111 hwTimer::callbackTock();
113 hwTimer::isTick
= !hwTimer::isTick
;
115 portEXIT_CRITICAL_ISR(&isrMutex
);