// 定时器驱动
// 杭州秒寻科技有限公司
// 周涛
// 2023-09-14

#include "includes.h"

// 2号定时器(32位)
uint32 gTimer_dwTimer2DelayBase = 31616; // 延迟一个周期的基数，约49400us
// uint32 gTimer_dwTimer2DelayBase = 1976;                                      // 延迟一个周期的基数，约49400us
static TIMER_CALLBACK_FUNC gTimer_pvCallBackFuncDelaySendAudioSignal = NULL; // 2号定时器超时回调函数指针(延迟发送音频信号)

// 3号定时器(16位)
static uint32 gTimer_dwTimer3Ticks = 0; // 定时器滴答计数器

// 定时器模块初始化
void driver_timer_init()
{
    driver_timer_timer3_init();
}

/************************************************以上模块初始化******************************************************/
/************************************************以下是2号定时器，用于延迟发送音频信号*********************************/
// 启动延迟发送音频信号定时器
// byTxFlag:同步信号转发标识符
// byDelayTimes:音频信号延迟周期数
// pvFunc:定时器溢出回调函数
void driver_timer_start_timer_delay_send_audio_signal(uint8 byTxFlag, uint8 byDelayTimes, TIMER_CALLBACK_FUNC pvFunc)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_TimeBaseInitTypeDef stTimer = {0};
    uint32 dwPeriod = 0;
    uint32 dwCounter = 340;

    gTimer_pvCallBackFuncDelaySendAudioSignal = pvFunc; // 保存函数指针

    // 补偿转发同步信号的时延
    // if (byDelayTimes == 1 || byDelayTimes == 2 || byDelayTimes == 3)
    // {
    //     dwPeriod = byDelayTimes * gTimer_dwTimer2DelayBase - (SYS_SYNC_WORD_MAX_ID - byDelayTimes) * 6;
    // }

    dwPeriod = byDelayTimes * gTimer_dwTimer2DelayBase;

    // 初始化中断向量
    NVIC_InitStructure.NVIC_IRQChannel = DRIVER_TIM_DELAY_SEND_SIGNALIRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能定时器时钟（APB1时钟为61.44MHz）
    RCC_APB1PeriphClockCmd(DRIVER_TIM_DELAY_SEND_SIGNALCLK, ENABLE);

    // 初始化定时器
    TIM_DeInit(DRIVER_TIM_DELAY_SEND_SIGNALNO);
    stTimer.TIM_Prescaler = 96 - 1; // 分频系数，每个周期1.5625us
    // stTimer.TIM_Prescaler = 1536 - 1;                               // 分频系数，每个周期25us
    stTimer.TIM_Period = dwPeriod - 1;                              // 重装寄存器，表示计数周期
    stTimer.TIM_CounterMode = TIM_CounterMode_Up;                   // 向上计数，计到最大值后产生中断
    TIM_TimeBaseInit(DRIVER_TIM_DELAY_SEND_SIGNALNO, &stTimer);     // 初始化
    TIM_ClearFlag(DRIVER_TIM_DELAY_SEND_SIGNALNO, TIM_FLAG_Update); // 清除所有中断标识符

    // 启动定时器，延迟发送信号
    if (byDelayTimes > 0 && byDelayTimes < SYS_SYNC_WORD_MAX_ID)
    {
        TIM_ITConfig(DRIVER_TIM_DELAY_SEND_SIGNALNO, TIM_IT_Update, ENABLE); // 使能中断
        TIM_Cmd(DRIVER_TIM_DELAY_SEND_SIGNALNO, ENABLE);                     // 使能定时器
    }
    else if (byDelayTimes == 0)
    // 直接发送信号
    {
        while (dwCounter > 0)
        {
            dwCounter--;
        }

        gTimer_pvCallBackFuncDelaySendAudioSignal(); // 发送音频信号
    }

    return;
}

// 2号定时器中断服务程序(负责发送音频数据)
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(DRIVER_TIM_DELAY_SEND_SIGNALNO, TIM_IT_Update) != RESET)
    {
        gTimer_pvCallBackFuncDelaySendAudioSignal(); // 发送音频信号

        TIM_Cmd(DRIVER_TIM_DELAY_SEND_SIGNALNO, DISABLE);                     // 关闭定时器
        TIM_ClearITPendingBit(DRIVER_TIM_DELAY_SEND_SIGNALNO, TIM_IT_Update); // 清除中断标识符
    }
}

/************************************************以上是2号定时器******************************************************/
/************************************************以下是3号定时器，用于为系统的延时函数提供时基***************************/

// 初始化定时器(500毫秒溢出一次)，使用3号通用定时器，该定时器给所有应用层提供定时时钟
void driver_timer_timer3_init()
{
    NVIC_InitTypeDef stNvic = {0};
    TIM_TimeBaseInitTypeDef stTimer = {0};

    // 配置NVIC
    stNvic.NVIC_IRQChannel = DRIVER_TIM_BASE_TIME_IRQn;
    stNvic.NVIC_IRQChannelCmd = ENABLE;
    stNvic.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级
    stNvic.NVIC_IRQChannelSubPriority = 0;        // 响应优先级
    NVIC_Init(&stNvic);

    // 使能定时器时钟（APB1时钟为61.44MHz）
    RCC_APB1PeriphClockCmd(DRIVER_TIM_BASE_TIME_CLK, ENABLE);

    // 初始化定时器
    TIM_DeInit(DRIVER_TIM_BASE_TIME_NO);
    stTimer.TIM_Prescaler = 6144 - 1;             // 分频系数，10000(10kHz) = 61440000/6144，每个周期100us
    stTimer.TIM_Period = 5000 - 1;                // 重装寄存器，表示计数次数，500ms = 5000 * 100us
    stTimer.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数，计到最大值后产生中断
    TIM_TimeBaseInit(DRIVER_TIM_BASE_TIME_NO, &stTimer);

    // 开启定时器中断
    TIM_ITConfig(DRIVER_TIM_BASE_TIME_NO, TIM_IT_Update, ENABLE);

    // 使能定时器3
    TIM_Cmd(DRIVER_TIM_BASE_TIME_NO, ENABLE);

    return;
}

// 定时器3的中断服务入口（500毫秒进一次中断）
void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(DRIVER_TIM_BASE_TIME_NO, TIM_IT_Update) == SET)
    {
        gTimer_dwTimer3Ticks++;                                        // 时基计数器加1
        TIM_ClearITPendingBit(DRIVER_TIM_BASE_TIME_NO, TIM_IT_Update); // 清除中断标识符
    }

    return;
}

// 获得计数器滴答值
void driver_timer_timer3_get_ticks(uint32 *pdwTicks)
{
    *pdwTicks = gTimer_dwTimer3Ticks;

    return;
}
