3 #if defined(ESP32) && defined(ARDUINO)
4 #include <esp_task_wdt.h>
6 #include "AudioTools/CoreAudio/AudioTimer/AudioTimerBase.h"
18 void setup(repeating_timer_callback_t my_callback,
void *user_data,
21 this->my_callback = my_callback;
22 this->user_data = user_data;
26 IRAM_ATTR
void call() {
27 if (my_callback !=
nullptr) {
28 if (lock) portENTER_CRITICAL_ISR(&timerMux);
29 my_callback(user_data);
30 if (lock) portEXIT_CRITICAL_ISR(&timerMux);
35 repeating_timer_callback_t my_callback =
nullptr;
36 void *user_data =
nullptr;
37 portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
40 }
static *simpleUserCallback =
nullptr;
42 static IRAM_ATTR
void userCallback0() { simpleUserCallback[0].call(); }
43 static IRAM_ATTR
void userCallback1() { simpleUserCallback[1].call(); }
44 static IRAM_ATTR
void userCallback2() { simpleUserCallback[2].call(); }
45 static IRAM_ATTR
void userCallback3() { simpleUserCallback[3].call(); }
57 timerMux = portMUX_INITIALIZER_UNLOCKED;
58 p_handler_task =
nullptr;
61 void setup(TaskHandle_t handler_task) {
63 p_handler_task = handler_task;
64 assert(handler_task !=
nullptr);
67 IRAM_ATTR
void call() {
68 if (p_handler_task !=
nullptr) {
71 portENTER_CRITICAL_ISR(&timerMux);
72 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
73 vTaskNotifyGiveFromISR(p_handler_task, &xHigherPriorityTaskWoken);
74 if (xHigherPriorityTaskWoken) {
77 portEXIT_CRITICAL_ISR(&timerMux);
82 portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
83 TaskHandle_t p_handler_task =
nullptr;
85 }
static *timerCallbackArray =
nullptr;
87 static IRAM_ATTR
void timerCallback0() { timerCallbackArray[0].call(); }
88 static IRAM_ATTR
void timerCallback1() { timerCallbackArray[1].call(); }
89 static IRAM_ATTR
void timerCallback2() { timerCallbackArray[2].call(); }
90 static IRAM_ATTR
void timerCallback3() { timerCallbackArray[3].call(); }
102 class TimerAlarmRepeatingDriverESP32 :
public TimerAlarmRepeatingDriverBase {
104 TimerAlarmRepeatingDriverESP32() {
105 setTimerFunction(DirectTimerCallback);
109 TimerAlarmRepeatingDriverESP32(
int timer, TimerFunction
function) {
110 setTimerFunction(
function);
114 void setTimer(
int id)
override {
115 if (
id >= 0 &&
id < 4) {
117 handler_task =
nullptr;
119 LOGE(
"Invalid timer id %d", timer_id);
123 void setTimerFunction(TimerFunction
function = DirectTimerCallback)
override {
124 this->
function =
function;
128 bool begin(repeating_timer_callback_t callback_f, uint32_t time,
135 timeUs = time * 1000;
145 #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)
146 LOGI(
"Timer every: %u us", timeUs);
147 adc_timer = timerBegin(timer_id, 80,
150 uint32_t freq = AudioTime::AudioTime::toRateUs(timeUs);
151 LOGI(
"Timer freq: %u hz", (
unsigned)freq);
152 adc_timer = timerBegin(1000000);
155 case DirectTimerCallback:
156 setupDirectTimerCallback(callback_f);
159 case TimerCallbackInThread:
160 setupTimerCallbackInThread(callback_f);
163 case SimpleThreadLoop:
164 setupSimpleThreadLoop(callback_f);
173 bool end()
override {
176 timerDetachInterrupt(adc_timer);
178 if (handler_task !=
nullptr) {
179 vTaskDelete(handler_task);
180 handler_task =
nullptr;
187 void setCore(
int core) { this->core = core; }
191 void setIsSave(
bool is_save)
override {
192 setTimerFunction(is_save ? TimerCallbackInThread : DirectTimerCallback);
197 volatile bool started =
false;
198 TaskHandle_t handler_task =
nullptr;
199 hw_timer_t *adc_timer =
nullptr;
200 UserCallback user_callback;
201 TimerFunction
function;
207 void attach(hw_timer_t *timer,
void (*cb)()) {
208 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
209 timerAttachInterrupt(timer, cb);
211 timerAttachInterrupt(timer, cb,
false);
216 void setupDirectTimerCallback(repeating_timer_callback_t callback_f) {
219 if (simpleUserCallback ==
nullptr) {
220 simpleUserCallback =
new UserCallback[4];
222 simpleUserCallback[timer_id].setup(callback_f,
object,
true);
225 attach(adc_timer, userCallback0);
226 else if (timer_id == 1)
227 attach(adc_timer, userCallback1);
228 else if (timer_id == 2)
229 attach(adc_timer, userCallback2);
230 else if (timer_id == 3)
231 attach(adc_timer, userCallback3);
233 #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)
234 timerAlarmWrite(adc_timer, timeUs,
true);
235 timerAlarmEnable(adc_timer);
240 timerAlarm(adc_timer, timeUs,
true, 0);
246 void setupTimerCallbackInThread(repeating_timer_callback_t callback_f) {
249 if (timerCallbackArray ==
nullptr) {
250 timerCallbackArray =
new TimerCallback[4];
254 attach(adc_timer, timerCallback0);
255 else if (timer_id == 1)
256 attach(adc_timer, timerCallback1);
257 else if (timer_id == 2)
258 attach(adc_timer, timerCallback2);
259 else if (timer_id == 3)
260 attach(adc_timer, timerCallback3);
263 user_callback.setup(callback_f,
object,
false);
265 xTaskCreatePinnedToCore(complexTaskHandler,
"TimerAlarmRepeatingTask",
266 configMINIMAL_STACK_SIZE + 10000, &user_callback,
267 priority, &handler_task, core);
268 LOGI(
"Task created on core %d", core);
269 timerCallbackArray[timer_id].setup(handler_task);
271 #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)
272 timerAlarmWrite(adc_timer, timeUs,
true);
273 timerAlarmEnable(adc_timer);
275 timerAlarm(adc_timer, timeUs,
true, 0);
280 void setupSimpleThreadLoop(repeating_timer_callback_t callback_f) {
282 user_callback.setup(callback_f,
object,
false);
283 xTaskCreatePinnedToCore(simpleTaskLoop,
"TimerAlarmRepeatingTask",
284 configMINIMAL_STACK_SIZE + 10000,
this, priority,
285 &handler_task, core);
286 LOGI(
"Task created on core %d", core);
291 static void complexTaskHandler(
void *param) {
293 UserCallback *cb = (UserCallback *)param;
297 uint32_t thread_notification =
298 ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000));
300 if (thread_notification) {
309 static void simpleTaskLoop(
void *param) {
311 TimerAlarmRepeatingDriverESP32 *ta =
312 (TimerAlarmRepeatingDriverESP32 *)param;
315 unsigned long end = micros() + ta->timeUs;
316 ta->user_callback.call();
317 long waitUs = end - micros();
318 long waitMs = waitUs / 1000;
319 waitUs = waitUs - (waitMs * 1000);
321 waitUs = end - micros();
323 delayMicroseconds(waitUs);
TimeUnit
Time Units.
Definition: AudioTypes.h:45