#include <Arduino_FreeRTOS.h>
#include <timers.h>
#include <task.h>

// Định nghĩa các khoảng thời gian cho các timer tính bằng mili giây, chuyển đổi thành ticks
#define mainONE_SHOT_TIMER_PERIOD pdMS_TO_TICKS(3333)
#define mainAUTO_RELOAD_TIMER_PERIOD pdMS_TO_TICKS(500)

// Biến lưu trữ handle của timer cho timer one-shot và auto-reload
TimerHandle_t xAutoReloadTimer, xOneShotTimer;
BaseType_t xTimer1Started, xTimer2Started;

// Khai báo nguyên mẫu hàm cho các callback của timer
static void prvOneShotTimerCallback(TimerHandle_t xTimer);
static void prvAutoReloadTimerCallback(TimerHandle_t xTimer);

void setup() {
    Serial.begin(9600); // Bật giao tiếp serial với baud rate là 9600

    // Tạo timer one-shot
    xOneShotTimer = xTimerCreate(
        "OneShot",                      // Tên của timer (không được sử dụng bởi FreeRTOS)
        mainONE_SHOT_TIMER_PERIOD,       // Thời gian chạy của timer tính bằng ticks
        pdFALSE,                        // Không tự động khởi động lại sau khi hết thời gian
        0,                              // Không sử dụng timer id trong ví dụ này
        prvOneShotTimerCallback         // Hàm callback được gọi khi timer kết thúc
    );

    // Tạo timer auto-reload
    xAutoReloadTimer = xTimerCreate(
        "AutoReload",                   // Tên của timer (không được sử dụng bởi FreeRTOS)
        mainAUTO_RELOAD_TIMER_PERIOD,   // Thời gian chạy của timer tính bằng ticks
        pdTRUE,                         // Tự động khởi động lại sau mỗi chu kỳ
        0,                              // Không sử dụng timer id trong ví dụ này
        prvAutoReloadTimerCallback      // Hàm callback được gọi khi timer kết thúc
    );

    // Kiểm tra xem các timer đã được tạo thành công chưa
    if ((xOneShotTimer != NULL) && (xAutoReloadTimer != NULL)) {
        // Khởi động timer one-shot và timer auto-reload
        xTimer1Started = xTimerStart(xOneShotTimer, 0);
        xTimer2Started = xTimerStart(xAutoReloadTimer, 0);

        // Kiểm tra xem việc khởi động timer đã thành công hay chưa
        if ((xTimer1Started == pdPASS) && (xTimer2Started == pdPASS)) {
            // Khởi động bộ lập lịch của FreeRTOS
            vTaskStartScheduler();
        }
    }
}

void loop() {
    // Không có mã nguồn bổ sung trong hàm loop vì mọi task được quản lý bởi FreeRTOS
}

// Callback function cho timer one-shot
static void prvOneShotTimerCallback(TimerHandle_t xTimer) {
    TickType_t xTimeNow;
    xTimeNow = xTaskGetTickCount(); // Lấy số tick hiện tại
    Serial.print("One-shot timer callback executing ");
    Serial.println(xTimeNow / 31); // In ra serial monitor thời điểm callback được gọi
}

// Callback function cho timer auto-reload
static void prvAutoReloadTimerCallback(TimerHandle_t xTimer) {
    TickType_t xTimeNow;
    xTimeNow = xTaskGetTickCount(); // Lấy số tick hiện tại
    Serial.print("Auto-reload timer callback executing ");
    Serial.println(xTimeNow / 31); // In ra serial monitor thời điểm callback được gọi
}