#include "app_timer.h"
#include "app.h"

/* 函数声明 */
static void app_timer_task(void);
static void app_timer_init(u8 task_num, app_timer_class_t *p_timer_class);
static void app_timer_task_increment_int(u16 ms_tick);

/******************************************
 * 结构体: app_timer
 * 功能: 应用定时器实例
 * 描述: 定时器控制结构体的具体实例
*******************************************/
app_timer_t app_timer = 
{
    .p_timer_class = NULL,
    .init = app_timer_init,
    .task = app_timer_task,
    .increment_int = app_timer_task_increment_int,
};

/* 全局指针，指向定时器结构体 */
app_timer_t *p_app_timer = &app_timer;

/******************************************
 * 函数: app_timer_init
 * 功能: 定时器初始化
 * 参数: task_num - 任务数量
 *       p_timer_class - 任务时间片数组指针
 * 返回: 无
 * 描述: 初始化定时器，设置任务数量和任务数组
*******************************************/
static void app_timer_init(u8 task_num, app_timer_class_t *p_timer_class)
{
    p_app_timer->task_num = task_num;
    p_app_timer->p_timer_class = p_timer_class;
}

/******************************************
 * 函数: app_timer_task
 * 功能: 定时器任务调度
 * 参数: 无
 * 返回: 无
 * 描述: 执行所有已到时间的任务
*******************************************/
static void app_timer_task(void)
{
    u16 i;
    
    /* 检查任务数组是否有效 */
    if(NULL == p_app_timer->p_timer_class)
    {
        return;
    }
    
    /* 遍历所有任务 */
    for (i = 0; i < p_app_timer->task_num; i++)
    {
        /* 检查任务是否需要执行 */
        if (p_app_timer->p_timer_class[i].run_flag) 
        {
            p_app_timer->p_timer_class[i].run_flag = 0;  /* 清除执行标志 */
            
            /* 检查任务函数是否有效 */
            if (p_app_timer->p_timer_class[i].task == NULL)
            {
                continue;
            }
            
            /* 执行任务函数 */
            p_app_timer->p_timer_class[i].task(); 
        }
    }
}

/******************************************
 * 函数: app_timer_task_increment_int
 * 功能: 中断递增函数
 * 参数: ms_tick - 毫秒增量
 * 返回: 无
 * 描述: 在中断中调用，更新定时器计数器和检查任务时间片
*******************************************/
static void app_timer_task_increment_int(u16 ms_tick)
{
    u16 i;
    
    /* 更新毫秒级计数器 */
    p_app_timer->ms_tick++;             
    
    /* 更新秒级计数器 */
    if(p_app_timer->ms_tick >= 1000)    
    {
        p_app_timer->s_tick++;          
    }
    
    /* 检查任务数组是否有效 */
    if(NULL == p_app_timer->p_timer_class)
    {
        return;
    }
    
    /* 更新所有任务的时间片计数器 */
    for (i = 0; i < p_app_timer->task_num; i++)
    {
        /* 检查任务计数器是否有效 */
        if (p_app_timer->p_timer_class[i].timer_count)
        {
            p_app_timer->p_timer_class[i].timer_count--;
            
            /* 检查是否到达任务执行时间 */
            if (p_app_timer->p_timer_class[i].timer_count == 0)
            {
                p_app_timer->p_timer_class[i].run_flag = 1;
                p_app_timer->p_timer_class[i].timer_count = p_app_timer->p_timer_class[i].timer_reload;
            }
        }
    }
}

/******************************************
 * 函数: app_timer_check_time_out
 * 功能: 检查超时
 * 参数: time_start - 计时开始时间
 *       time_now - 当前时间
 *       time_out - 超时时间
 * 返回: TIME_TRUE - 已超时，TIME_FALSE - 未超时
 * 描述: 检查从time_start开始经过time_out时间后是否超时，
 *       考虑了计数器溢出的情况
*******************************************/
u8 app_timer_check_time_out(u16 time_start, u16 time_now, u16 time_out)
{
    u16 timer_activate_val;
    
    /* 计算触发时间 */
    timer_activate_val = time_out + time_start;
    
    /* 考虑计数器溢出情况 */
    if (timer_activate_val > time_start)
    {
        /* 未发生溢出 */
        if ((time_now >= timer_activate_val) || (time_now < time_start))
        {
            return TIME_TRUE;
        }
    }
    else if ((time_now >= timer_activate_val) && (time_now < time_start))
    {
        /* 发生溢出且当前时间在溢出后 */
        return TIME_TRUE;
    }
    
    return TIME_FALSE;
}

/******************************************
 * 函数: app_timer_check_run_time
 * 功能: 计算剩余运行时间
 * 参数: time_start - 计时开始时间
 *       time_now - 当前时间
 *       time_out - 超时时间
 * 返回: 剩余时间（毫秒）
 * 描述: 配合app_timer_check_time_out函数使用，
 *       计算距离超时还有多少时间，考虑了计数器溢出
*******************************************/
u16 app_timer_check_run_time(u16 time_start, u16 time_now, u16 time_out)
{
    u16 timer_activate_val;
    
    /* 计算触发时间 */
    timer_activate_val = time_out + time_start;
    
    /* 考虑计数器溢出情况 */
    if (timer_activate_val > time_start)
    {
        /* 未发生溢出，直接计算剩余时间 */ 
        return (timer_activate_val - time_now);
    }
    else
    {
        /* 发生溢出，计算溢出后的剩余时间 */
        return (65535U - time_now + timer_activate_val);
    }
}

/******************************************
 * 函数: delay_ms
 * 功能: 阻塞式延时
 * 参数: delay - 延时时间（毫秒）
 * 返回: 无
 * 描述: 使用HAL库提供的延时函数实现阻塞式延时
*******************************************/
void delay_ms(u16 delay)
{
    HAL_Delay(delay);
}
